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 * 837128Sbostic * Redistribution and use in source and binary forms are permitted 937128Sbostic * provided that the above copyright notice and this paragraph are 1037128Sbostic * duplicated in all such forms and that any documentation, 1137128Sbostic * advertising materials, and other materials related to such 1237128Sbostic * distribution and use acknowledge that the software was developed 1337128Sbostic * by the University of California, Berkeley. The name of the 1437128Sbostic * University may not be used to endorse or promote products derived 1537128Sbostic * from this software without specific prior written permission. 1637128Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1737128Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1837128Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1919840Sdist */ 2019840Sdist 2114463Ssam #ifndef lint 2234079Sbostic char copyright[] = 2337128Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 2434079Sbostic All rights reserved.\n"; 2534079Sbostic #endif /* not lint */ 2614463Ssam 2734079Sbostic #ifndef lint 28*40268Sbostic static char sccsid[] = "@(#)cat.c 5.10 (Berkeley) 03/05/90"; 2934079Sbostic #endif /* not lint */ 3034079Sbostic 3137178Sbostic #include <sys/param.h> 3237178Sbostic #include <sys/stat.h> 3337178Sbostic #include <sys/file.h> 34962Sbill #include <stdio.h> 3537128Sbostic #include <ctype.h> 36962Sbill 37*40268Sbostic extern int errno; 3837179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag; 3937179Sbostic int rval; 4037128Sbostic char *filename; 41962Sbill 42962Sbill main(argc, argv) 4337128Sbostic int argc; 4437128Sbostic char **argv; 45962Sbill { 46*40268Sbostic extern int optind; 4737179Sbostic int ch; 4837128Sbostic char *strerror(); 49962Sbill 5039713Sbostic while ((ch = getopt(argc, argv, "benstuv")) != EOF) 5137128Sbostic switch (ch) { 5237179Sbostic case 'b': 5337179Sbostic bflag = nflag = 1; /* -b implies -n */ 54962Sbill break; 5537179Sbostic case 'e': 5637179Sbostic eflag = vflag = 1; /* -e implies -v */ 5737179Sbostic break; 5837179Sbostic case 'n': 5937179Sbostic nflag = 1; 6037179Sbostic break; 6137179Sbostic case 's': 6237179Sbostic sflag = 1; 6337179Sbostic break; 6437179Sbostic case 't': 6537179Sbostic tflag = vflag = 1; /* -t implies -v */ 6637179Sbostic break; 6737179Sbostic case 'u': 6837179Sbostic setbuf(stdout, (char *)NULL); 6937179Sbostic break; 7037179Sbostic case 'v': 7137179Sbostic vflag = 1; 7237179Sbostic break; 7337128Sbostic case '?': 7437128Sbostic (void)fprintf(stderr, 7537179Sbostic "usage: cat [-benstuv] [-] [file ...]\n"); 7637128Sbostic exit(1); 77962Sbill } 7839713Sbostic argv += optind; 7937128Sbostic 8037179Sbostic if (bflag || eflag || nflag || sflag || tflag || vflag) 8137179Sbostic cook_args(argv); 8237179Sbostic else 8337179Sbostic raw_args(argv); 8437179Sbostic exit(rval); 8537179Sbostic } 8637179Sbostic 8737179Sbostic cook_args(argv) 8837179Sbostic char **argv; 8937179Sbostic { 9037179Sbostic register FILE *fp; 9137179Sbostic 9237179Sbostic fp = stdin; 9337179Sbostic filename = "-"; 9437179Sbostic do { 9537179Sbostic if (*argv) { 9637179Sbostic if (!strcmp(*argv, "-")) 9737179Sbostic fp = stdin; 9837179Sbostic else if (!(fp = fopen(*argv, "r"))) { 9937179Sbostic (void)fprintf(stderr, 10037179Sbostic "cat: %s: %s\n", *argv, strerror(errno)); 10137179Sbostic rval = 1; 10237179Sbostic ++argv; 10337179Sbostic continue; 10437179Sbostic } 10537179Sbostic filename = *argv++; 10637179Sbostic } 10737179Sbostic cook_buf(fp); 10837179Sbostic if (fp != stdin) 10937179Sbostic (void)fclose(fp); 11037179Sbostic } while (*argv); 11137179Sbostic } 11237179Sbostic 11337179Sbostic cook_buf(fp) 11437179Sbostic register FILE *fp; 11537179Sbostic { 11637179Sbostic register int ch, gobble, line, prev; 11737179Sbostic 11837179Sbostic line = gobble = 0; 11937179Sbostic for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 12037179Sbostic if (prev == '\n') { 12137179Sbostic if (ch == '\n') { 12237179Sbostic if (sflag) { 12338900Sbostic if (!gobble && putchar(ch) == EOF) 12438471Sbostic break; 12537179Sbostic gobble = 1; 12638471Sbostic continue; 12737179Sbostic } 12837179Sbostic if (nflag && !bflag) { 12937179Sbostic (void)fprintf(stdout, "%6d\t", ++line); 13037179Sbostic if (ferror(stdout)) 13137179Sbostic break; 13237179Sbostic } 13338471Sbostic } else if (nflag) { 13437179Sbostic (void)fprintf(stdout, "%6d\t", ++line); 13537179Sbostic if (ferror(stdout)) 13637179Sbostic break; 13737179Sbostic } 13837179Sbostic } 13938471Sbostic gobble = 0; 14037179Sbostic if (ch == '\n') { 14137179Sbostic if (eflag) 14238900Sbostic if (putchar('$') == EOF) 14337179Sbostic break; 14437179Sbostic } else if (ch == '\t') { 14537179Sbostic if (tflag) { 14638900Sbostic if (putchar('^') == EOF || putchar('I') == EOF) 14737179Sbostic break; 14837179Sbostic continue; 14937179Sbostic } 15037179Sbostic } else if (vflag) { 15138900Sbostic if (!isascii(ch)) { 15238900Sbostic if (putchar('M') == EOF || putchar('-') == EOF) 15337179Sbostic break; 15438900Sbostic ch = toascii(ch); 15537179Sbostic } 15637179Sbostic if (iscntrl(ch)) { 15738900Sbostic if (putchar('^') == EOF || 15838900Sbostic putchar(ch == '\177' ? '?' : 15938900Sbostic ch | 0100) == EOF) 16037179Sbostic break; 16137179Sbostic continue; 16237179Sbostic } 16337179Sbostic } 16438900Sbostic if (putchar(ch) == EOF) 16537179Sbostic break; 16637179Sbostic } 16737179Sbostic if (ferror(fp)) { 16837179Sbostic (void)fprintf(stderr, "cat: %s: read error\n", filename); 16937179Sbostic rval = 1; 17037179Sbostic } 17137179Sbostic if (ferror(stdout)) { 17237179Sbostic clearerr(stdout); 17337179Sbostic (void)fprintf(stderr, "cat: stdout: write error\n"); 17437179Sbostic rval = 1; 17537179Sbostic } 17637179Sbostic } 17737179Sbostic 17837179Sbostic raw_args(argv) 17937179Sbostic char **argv; 18037179Sbostic { 18137179Sbostic register int fd; 18237179Sbostic 18337178Sbostic fd = fileno(stdin); 18437128Sbostic filename = "-"; 18537128Sbostic do { 18637128Sbostic if (*argv) { 18737178Sbostic if (!strcmp(*argv, "-")) 18837178Sbostic fd = fileno(stdin); 18937178Sbostic else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 19037178Sbostic (void)fprintf(stderr, "cat: %s: %s\n", 19137178Sbostic *argv, strerror(errno)); 19237178Sbostic rval = 1; 19337128Sbostic ++argv; 1944387Secc continue; 1954387Secc } 19637178Sbostic filename = *argv++; 197962Sbill } 19837179Sbostic rval |= raw_cat(fd); 19937178Sbostic if (fd != fileno(stdin)) 20037178Sbostic (void)close(fd); 20137128Sbostic } while (*argv); 202962Sbill } 2031357Sbill 20437179Sbostic raw_cat(fd) 20537128Sbostic register int fd; 20617947Sralph { 20737128Sbostic register int nr, nw, off; 20837178Sbostic static int bsize; 20937178Sbostic static char *buf; 21037178Sbostic struct stat sbuf; 21137178Sbostic char *malloc(), *strerror(); 21217947Sralph 21337178Sbostic if (!buf) { 21437178Sbostic if (fstat(fileno(stdout), &sbuf)) { 21537178Sbostic (void)fprintf(stderr, "cat: %s: %s\n", filename, 21637178Sbostic strerror(errno)); 21737178Sbostic return(1); 21837178Sbostic } 21937178Sbostic bsize = MAX(sbuf.st_blksize, 1024); 22037178Sbostic if (!(buf = malloc((u_int)bsize))) { 22137179Sbostic (void)fprintf(stderr, "cat: %s: no memory.\n", 22237179Sbostic filename); 22337178Sbostic return(1); 22437178Sbostic } 22537178Sbostic } 22637178Sbostic while ((nr = read(fd, buf, bsize)) > 0) 22737128Sbostic for (off = 0; off < nr;) { 22837128Sbostic if ((nw = write(fileno(stdout), buf + off, nr)) < 0) { 22937128Sbostic perror("cat: stdout"); 23037178Sbostic return(1); 23117965Skarels } 23237128Sbostic off += nw; 23337128Sbostic } 23437128Sbostic if (nr < 0) { 23537128Sbostic (void)fprintf(stderr, "cat: %s: %s\n", filename, 23637128Sbostic strerror(errno)); 23737178Sbostic return(1); 23817947Sralph } 23937178Sbostic return(0); 24017947Sralph } 241