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*37179Sbostic static char sccsid[] = "@(#)cat.c 5.6 (Berkeley) 03/15/89"; 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*37179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag; 38*37179Sbostic int rval; 3937128Sbostic char *filename; 40962Sbill 41962Sbill main(argc, argv) 4237128Sbostic int argc; 4337128Sbostic char **argv; 44962Sbill { 4537128Sbostic extern int errno, optind; 46*37179Sbostic int ch; 4737128Sbostic char *strerror(); 48962Sbill 49*37179Sbostic while ((ch = getopt(argc, argv, "-benstuv")) != EOF) 5037128Sbostic switch (ch) { 5137128Sbostic case '-': 5237128Sbostic --optind; 5337128Sbostic goto done; 54*37179Sbostic case 'b': 55*37179Sbostic bflag = nflag = 1; /* -b implies -n */ 56962Sbill break; 57*37179Sbostic case 'e': 58*37179Sbostic eflag = vflag = 1; /* -e implies -v */ 59*37179Sbostic break; 60*37179Sbostic case 'n': 61*37179Sbostic nflag = 1; 62*37179Sbostic break; 63*37179Sbostic case 's': 64*37179Sbostic sflag = 1; 65*37179Sbostic break; 66*37179Sbostic case 't': 67*37179Sbostic tflag = vflag = 1; /* -t implies -v */ 68*37179Sbostic break; 69*37179Sbostic case 'u': 70*37179Sbostic setbuf(stdout, (char *)NULL); 71*37179Sbostic break; 72*37179Sbostic case 'v': 73*37179Sbostic vflag = 1; 74*37179Sbostic break; 7537128Sbostic case '?': 7637128Sbostic (void)fprintf(stderr, 77*37179Sbostic "usage: cat [-benstuv] [-] [file ...]\n"); 7837128Sbostic exit(1); 79962Sbill } 8037128Sbostic done: argv += optind; 8137128Sbostic 82*37179Sbostic if (bflag || eflag || nflag || sflag || tflag || vflag) 83*37179Sbostic cook_args(argv); 84*37179Sbostic else 85*37179Sbostic raw_args(argv); 86*37179Sbostic exit(rval); 87*37179Sbostic } 88*37179Sbostic 89*37179Sbostic cook_args(argv) 90*37179Sbostic char **argv; 91*37179Sbostic { 92*37179Sbostic register FILE *fp; 93*37179Sbostic 94*37179Sbostic fp = stdin; 95*37179Sbostic filename = "-"; 96*37179Sbostic do { 97*37179Sbostic if (*argv) { 98*37179Sbostic if (!strcmp(*argv, "-")) 99*37179Sbostic fp = stdin; 100*37179Sbostic else if (!(fp = fopen(*argv, "r"))) { 101*37179Sbostic (void)fprintf(stderr, 102*37179Sbostic "cat: %s: %s\n", *argv, strerror(errno)); 103*37179Sbostic rval = 1; 104*37179Sbostic ++argv; 105*37179Sbostic continue; 106*37179Sbostic } 107*37179Sbostic filename = *argv++; 108*37179Sbostic } 109*37179Sbostic cook_buf(fp); 110*37179Sbostic if (fp != stdin) 111*37179Sbostic (void)fclose(fp); 112*37179Sbostic } while (*argv); 113*37179Sbostic } 114*37179Sbostic 115*37179Sbostic cook_buf(fp) 116*37179Sbostic register FILE *fp; 117*37179Sbostic { 118*37179Sbostic register int ch, gobble, line, prev; 119*37179Sbostic 120*37179Sbostic line = gobble = 0; 121*37179Sbostic for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 122*37179Sbostic if (prev == '\n') { 123*37179Sbostic if (ch == '\n') { 124*37179Sbostic if (sflag) { 125*37179Sbostic if (gobble) 126*37179Sbostic continue; 127*37179Sbostic gobble = 1; 128*37179Sbostic } 129*37179Sbostic if (nflag && !bflag) { 130*37179Sbostic (void)fprintf(stdout, "%6d\t", ++line); 131*37179Sbostic if (ferror(stdout)) 132*37179Sbostic break; 133*37179Sbostic } 134*37179Sbostic } 135*37179Sbostic else if (nflag) { 136*37179Sbostic (void)fprintf(stdout, "%6d\t", ++line); 137*37179Sbostic if (ferror(stdout)) 138*37179Sbostic break; 139*37179Sbostic } 140*37179Sbostic } 141*37179Sbostic if (ch == '\n') { 142*37179Sbostic if (eflag) 143*37179Sbostic if (putc('$', stdout) == EOF) 144*37179Sbostic break; 145*37179Sbostic } else if (ch == '\t') { 146*37179Sbostic if (tflag) { 147*37179Sbostic if (putc('^', stdout) == EOF || 148*37179Sbostic putc('I', stdout) == EOF) 149*37179Sbostic break; 150*37179Sbostic continue; 151*37179Sbostic } 152*37179Sbostic } else if (vflag) { 153*37179Sbostic if (ch > 0177) { 154*37179Sbostic if (putc('M', stdout) == EOF || 155*37179Sbostic putc('-', stdout) == EOF) 156*37179Sbostic break; 157*37179Sbostic ch &= 0177; 158*37179Sbostic } 159*37179Sbostic if (iscntrl(ch)) { 160*37179Sbostic if (putc('^', stdout) == EOF || 161*37179Sbostic putc(ch == '\177' ? '?' : 162*37179Sbostic ch | 0100, stdout) == EOF) 163*37179Sbostic break; 164*37179Sbostic continue; 165*37179Sbostic } 166*37179Sbostic } 167*37179Sbostic if (putc(ch, stdout) == EOF) 168*37179Sbostic break; 169*37179Sbostic } 170*37179Sbostic if (ferror(fp)) { 171*37179Sbostic (void)fprintf(stderr, "cat: %s: read error\n", filename); 172*37179Sbostic rval = 1; 173*37179Sbostic } 174*37179Sbostic if (ferror(stdout)) { 175*37179Sbostic clearerr(stdout); 176*37179Sbostic (void)fprintf(stderr, "cat: stdout: write error\n"); 177*37179Sbostic rval = 1; 178*37179Sbostic } 179*37179Sbostic } 180*37179Sbostic 181*37179Sbostic raw_args(argv) 182*37179Sbostic char **argv; 183*37179Sbostic { 184*37179Sbostic register int fd; 185*37179Sbostic 18637178Sbostic fd = fileno(stdin); 18737128Sbostic filename = "-"; 18837128Sbostic do { 18937128Sbostic if (*argv) { 19037178Sbostic if (!strcmp(*argv, "-")) 19137178Sbostic fd = fileno(stdin); 19237178Sbostic else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 19337178Sbostic (void)fprintf(stderr, "cat: %s: %s\n", 19437178Sbostic *argv, strerror(errno)); 19537178Sbostic rval = 1; 19637128Sbostic ++argv; 1974387Secc continue; 1984387Secc } 19937178Sbostic filename = *argv++; 200962Sbill } 201*37179Sbostic rval |= raw_cat(fd); 20237178Sbostic if (fd != fileno(stdin)) 20337178Sbostic (void)close(fd); 20437128Sbostic } while (*argv); 205962Sbill } 2061357Sbill 207*37179Sbostic raw_cat(fd) 20837128Sbostic register int fd; 20917947Sralph { 21037128Sbostic extern int errno; 21137128Sbostic register int nr, nw, off; 21237178Sbostic static int bsize; 21337178Sbostic static char *buf; 21437178Sbostic struct stat sbuf; 21537178Sbostic char *malloc(), *strerror(); 21617947Sralph 21737178Sbostic if (!buf) { 21837178Sbostic if (fstat(fileno(stdout), &sbuf)) { 21937178Sbostic (void)fprintf(stderr, "cat: %s: %s\n", filename, 22037178Sbostic strerror(errno)); 22137178Sbostic return(1); 22237178Sbostic } 22337178Sbostic bsize = MAX(sbuf.st_blksize, 1024); 22437178Sbostic if (!(buf = malloc((u_int)bsize))) { 225*37179Sbostic (void)fprintf(stderr, "cat: %s: no memory.\n", 226*37179Sbostic filename); 22737178Sbostic return(1); 22837178Sbostic } 22937178Sbostic } 23037178Sbostic while ((nr = read(fd, buf, bsize)) > 0) 23137128Sbostic for (off = 0; off < nr;) { 23237128Sbostic if ((nw = write(fileno(stdout), buf + off, nr)) < 0) { 23337128Sbostic perror("cat: stdout"); 23437178Sbostic return(1); 23517965Skarels } 23637128Sbostic off += nw; 23737128Sbostic } 23837128Sbostic if (nr < 0) { 23937128Sbostic (void)fprintf(stderr, "cat: %s: %s\n", filename, 24037128Sbostic strerror(errno)); 24137178Sbostic return(1); 24217947Sralph } 24337178Sbostic return(0); 24417947Sralph } 245