1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kevin Fall. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 char copyright[] = 23 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 24 All rights reserved.\n"; 25 #endif /* not lint */ 26 27 #ifndef lint 28 static char sccsid[] = "@(#)cat.c 5.4 (Berkeley) 03/11/89"; 29 #endif /* not lint */ 30 31 #include <stdio.h> 32 #include <ctype.h> 33 34 int bflag, eflag, nflag, sflag, tflag, vflag; 35 int rval; 36 char *filename; 37 38 main(argc, argv) 39 int argc; 40 char **argv; 41 { 42 extern int errno, optind; 43 register FILE *fp; 44 int ch; 45 char *strerror(); 46 47 while ((ch = getopt(argc, argv, "-benstuv")) != EOF) 48 switch (ch) { 49 case '-': 50 --optind; 51 goto done; 52 case 'b': 53 bflag = nflag = 1; /* -b implies -n */ 54 break; 55 case 'e': 56 eflag = vflag = 1; /* -e implies -v */ 57 break; 58 case 'n': 59 nflag = 1; 60 break; 61 case 's': 62 sflag = 1; 63 break; 64 case 't': 65 tflag = vflag = 1; /* -t implies -v */ 66 break; 67 case 'u': 68 setbuf(stdout, (char *)NULL); 69 break; 70 case 'v': 71 vflag = 1; 72 break; 73 case '?': 74 (void)fprintf(stderr, 75 "usage: cat [-benstuv] [-] [file ...]\n"); 76 exit(1); 77 } 78 done: argv += optind; 79 80 fp = stdin; 81 filename = "-"; 82 do { 83 if (*argv) { 84 if (!strcmp(*argv, "-")) { 85 fp = stdin; 86 filename = "-"; 87 } 88 else if (!(fp = fopen(filename = *argv, "r"))) { 89 (void)fprintf(stderr, 90 "cat: %s: %s\n", *argv, strerror(errno)); 91 ++argv; 92 continue; 93 } 94 ++argv; 95 } 96 if (bflag || eflag || nflag || sflag || tflag || vflag) 97 process_buf(fp); 98 else 99 rawcat(fileno(fp)); 100 if (fp != stdin) 101 (void)fclose(fp); 102 } while (*argv); 103 exit(rval); 104 } 105 106 process_buf(fp) 107 register FILE *fp; 108 { 109 register int ch, gobble, line, prev; 110 111 line = gobble = 0; 112 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 113 if (prev == '\n') { 114 if (ch == '\n') { 115 if (sflag) { 116 if (gobble) 117 continue; 118 gobble = 1; 119 } 120 if (nflag && !bflag) { 121 (void)fprintf(stdout, "%6d\t", ++line); 122 if (ferror(stdout)) 123 break; 124 } 125 } 126 else if (nflag) { 127 (void)fprintf(stdout, "%6d\t", ++line); 128 if (ferror(stdout)) 129 break; 130 } 131 } 132 if (ch == '\n') { 133 if (eflag) 134 if (putc('$', stdout) == EOF) 135 break; 136 } else if (ch == '\t') { 137 if (tflag) { 138 if (putc('^', stdout) == EOF || 139 putc('I', stdout) == EOF) 140 break; 141 continue; 142 } 143 } else if (vflag) { 144 if (ch > 0177) { 145 if (putc('M', stdout) == EOF || 146 putc('-', stdout) == EOF) 147 break; 148 ch &= 0177; 149 } 150 if (iscntrl(ch)) { 151 if (putc('^', stdout) == EOF || 152 putc(ch == '\177' ? '?' : 153 ch | 0100, stdout) == EOF) 154 break; 155 continue; 156 } 157 } 158 if (putc(ch, stdout) == EOF) 159 break; 160 } 161 if (ferror(fp)) { 162 (void)fprintf(stderr, "cat: %s: read error\n", filename); 163 rval = 1; 164 } 165 if (ferror(stdout)) { 166 clearerr(stdout); 167 (void)fprintf(stderr, "cat: stdout: write error\n"); 168 rval = 1; 169 } 170 } 171 172 rawcat(fd) 173 register int fd; 174 { 175 extern int errno; 176 static char buf[8*1024]; 177 register int nr, nw, off; 178 char *strerror(); 179 180 while ((nr = read(fd, buf, sizeof(buf))) > 0) 181 for (off = 0; off < nr;) { 182 if ((nw = write(fileno(stdout), buf + off, nr)) < 0) { 183 perror("cat: stdout"); 184 rval = 1; 185 return; 186 } 187 off += nw; 188 } 189 if (nr < 0) { 190 (void)fprintf(stderr, "cat: %s: %s\n", filename, 191 strerror(errno)); 192 rval = 1; 193 } 194 } 195