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*45857Sbostic static char sccsid[] = "@(#)cat.c 5.12 (Berkeley) 12/29/90"; 1934079Sbostic #endif /* not lint */ 2034079Sbostic 2137178Sbostic #include <sys/param.h> 2237178Sbostic #include <sys/stat.h> 2337178Sbostic #include <sys/file.h> 24962Sbill #include <stdio.h> 2537128Sbostic #include <ctype.h> 26962Sbill 2740268Sbostic extern int errno; 2837179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag; 2937179Sbostic int rval; 3037128Sbostic char *filename; 31962Sbill 32962Sbill main(argc, argv) 3337128Sbostic int argc; 3437128Sbostic char **argv; 35962Sbill { 3640268Sbostic extern int optind; 3737179Sbostic int ch; 3837128Sbostic char *strerror(); 39962Sbill 4039713Sbostic while ((ch = getopt(argc, argv, "benstuv")) != EOF) 4137128Sbostic switch (ch) { 4237179Sbostic case 'b': 4337179Sbostic bflag = nflag = 1; /* -b implies -n */ 44962Sbill break; 4537179Sbostic case 'e': 4637179Sbostic eflag = vflag = 1; /* -e implies -v */ 4737179Sbostic break; 4837179Sbostic case 'n': 4937179Sbostic nflag = 1; 5037179Sbostic break; 5137179Sbostic case 's': 5237179Sbostic sflag = 1; 5337179Sbostic break; 5437179Sbostic case 't': 5537179Sbostic tflag = vflag = 1; /* -t implies -v */ 5637179Sbostic break; 5737179Sbostic case 'u': 5837179Sbostic setbuf(stdout, (char *)NULL); 5937179Sbostic break; 6037179Sbostic case 'v': 6137179Sbostic vflag = 1; 6237179Sbostic break; 6337128Sbostic case '?': 6437128Sbostic (void)fprintf(stderr, 6537179Sbostic "usage: cat [-benstuv] [-] [file ...]\n"); 6637128Sbostic exit(1); 67962Sbill } 6839713Sbostic argv += optind; 6937128Sbostic 7037179Sbostic if (bflag || eflag || nflag || sflag || tflag || vflag) 7137179Sbostic cook_args(argv); 7237179Sbostic else 7337179Sbostic raw_args(argv); 7437179Sbostic exit(rval); 7537179Sbostic } 7637179Sbostic 7737179Sbostic cook_args(argv) 7837179Sbostic char **argv; 7937179Sbostic { 8037179Sbostic register FILE *fp; 8137179Sbostic 8237179Sbostic fp = stdin; 8337179Sbostic filename = "-"; 8437179Sbostic do { 8537179Sbostic if (*argv) { 8637179Sbostic if (!strcmp(*argv, "-")) 8737179Sbostic fp = stdin; 8837179Sbostic else if (!(fp = fopen(*argv, "r"))) { 8937179Sbostic (void)fprintf(stderr, 9037179Sbostic "cat: %s: %s\n", *argv, strerror(errno)); 9137179Sbostic rval = 1; 9237179Sbostic ++argv; 9337179Sbostic continue; 9437179Sbostic } 9537179Sbostic filename = *argv++; 9637179Sbostic } 9737179Sbostic cook_buf(fp); 9837179Sbostic if (fp != stdin) 9937179Sbostic (void)fclose(fp); 10037179Sbostic } while (*argv); 10137179Sbostic } 10237179Sbostic 10337179Sbostic cook_buf(fp) 10437179Sbostic register FILE *fp; 10537179Sbostic { 10637179Sbostic register int ch, gobble, line, prev; 10737179Sbostic 10837179Sbostic line = gobble = 0; 10937179Sbostic for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 11037179Sbostic if (prev == '\n') { 11137179Sbostic if (ch == '\n') { 11237179Sbostic if (sflag) { 11338900Sbostic if (!gobble && putchar(ch) == EOF) 11438471Sbostic break; 11537179Sbostic gobble = 1; 11638471Sbostic continue; 11737179Sbostic } 11837179Sbostic if (nflag && !bflag) { 11937179Sbostic (void)fprintf(stdout, "%6d\t", ++line); 12037179Sbostic if (ferror(stdout)) 12137179Sbostic break; 12237179Sbostic } 12338471Sbostic } else if (nflag) { 12437179Sbostic (void)fprintf(stdout, "%6d\t", ++line); 12537179Sbostic if (ferror(stdout)) 12637179Sbostic break; 12737179Sbostic } 12837179Sbostic } 12938471Sbostic gobble = 0; 13037179Sbostic if (ch == '\n') { 13137179Sbostic if (eflag) 13238900Sbostic if (putchar('$') == EOF) 13337179Sbostic break; 13437179Sbostic } else if (ch == '\t') { 13537179Sbostic if (tflag) { 13638900Sbostic if (putchar('^') == EOF || putchar('I') == EOF) 13737179Sbostic break; 13837179Sbostic continue; 13937179Sbostic } 14037179Sbostic } else if (vflag) { 14138900Sbostic if (!isascii(ch)) { 14238900Sbostic if (putchar('M') == EOF || putchar('-') == EOF) 14337179Sbostic break; 14438900Sbostic ch = toascii(ch); 14537179Sbostic } 14637179Sbostic if (iscntrl(ch)) { 14738900Sbostic if (putchar('^') == EOF || 14838900Sbostic putchar(ch == '\177' ? '?' : 14938900Sbostic ch | 0100) == EOF) 15037179Sbostic break; 15137179Sbostic continue; 15237179Sbostic } 15337179Sbostic } 15438900Sbostic if (putchar(ch) == EOF) 15537179Sbostic break; 15637179Sbostic } 15737179Sbostic if (ferror(fp)) { 15837179Sbostic (void)fprintf(stderr, "cat: %s: read error\n", filename); 15937179Sbostic rval = 1; 16037179Sbostic } 16137179Sbostic if (ferror(stdout)) { 16237179Sbostic clearerr(stdout); 16337179Sbostic (void)fprintf(stderr, "cat: stdout: write error\n"); 16437179Sbostic rval = 1; 16537179Sbostic } 16637179Sbostic } 16737179Sbostic 16837179Sbostic raw_args(argv) 16937179Sbostic char **argv; 17037179Sbostic { 17137179Sbostic register int fd; 17237179Sbostic 17337178Sbostic fd = fileno(stdin); 17437128Sbostic filename = "-"; 17537128Sbostic do { 17637128Sbostic if (*argv) { 17737178Sbostic if (!strcmp(*argv, "-")) 17837178Sbostic fd = fileno(stdin); 17937178Sbostic else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 18037178Sbostic (void)fprintf(stderr, "cat: %s: %s\n", 18137178Sbostic *argv, strerror(errno)); 18237178Sbostic rval = 1; 18337128Sbostic ++argv; 1844387Secc continue; 1854387Secc } 18637178Sbostic filename = *argv++; 187962Sbill } 18837179Sbostic rval |= raw_cat(fd); 18937178Sbostic if (fd != fileno(stdin)) 19037178Sbostic (void)close(fd); 19137128Sbostic } while (*argv); 192962Sbill } 1931357Sbill 19437179Sbostic raw_cat(fd) 19537128Sbostic register int fd; 19617947Sralph { 19737128Sbostic register int nr, nw, off; 19837178Sbostic static int bsize; 19937178Sbostic static char *buf; 20037178Sbostic struct stat sbuf; 20137178Sbostic char *malloc(), *strerror(); 20217947Sralph 20337178Sbostic if (!buf) { 20437178Sbostic if (fstat(fileno(stdout), &sbuf)) { 20537178Sbostic (void)fprintf(stderr, "cat: %s: %s\n", filename, 20637178Sbostic strerror(errno)); 20737178Sbostic return(1); 20837178Sbostic } 20937178Sbostic bsize = MAX(sbuf.st_blksize, 1024); 21037178Sbostic if (!(buf = malloc((u_int)bsize))) { 21137179Sbostic (void)fprintf(stderr, "cat: %s: no memory.\n", 21237179Sbostic filename); 21337178Sbostic return(1); 21437178Sbostic } 21537178Sbostic } 21637178Sbostic while ((nr = read(fd, buf, bsize)) > 0) 217*45857Sbostic for (off = 0; off < nr; nr -= nw, off += nw) 21837128Sbostic if ((nw = write(fileno(stdout), buf + off, nr)) < 0) { 21937128Sbostic perror("cat: stdout"); 22037178Sbostic return(1); 22117965Skarels } 22237128Sbostic if (nr < 0) { 22337128Sbostic (void)fprintf(stderr, "cat: %s: %s\n", filename, 22437128Sbostic strerror(errno)); 22537178Sbostic return(1); 22617947Sralph } 22737178Sbostic return(0); 22817947Sralph } 229