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 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 14 All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)cat.c 5.12 (Berkeley) 12/29/90"; 19 #endif /* not lint */ 20 21 #include <sys/param.h> 22 #include <sys/stat.h> 23 #include <sys/file.h> 24 #include <stdio.h> 25 #include <ctype.h> 26 27 extern int errno; 28 int bflag, eflag, nflag, sflag, tflag, vflag; 29 int rval; 30 char *filename; 31 32 main(argc, argv) 33 int argc; 34 char **argv; 35 { 36 extern int optind; 37 int ch; 38 char *strerror(); 39 40 while ((ch = getopt(argc, argv, "benstuv")) != EOF) 41 switch (ch) { 42 case 'b': 43 bflag = nflag = 1; /* -b implies -n */ 44 break; 45 case 'e': 46 eflag = vflag = 1; /* -e implies -v */ 47 break; 48 case 'n': 49 nflag = 1; 50 break; 51 case 's': 52 sflag = 1; 53 break; 54 case 't': 55 tflag = vflag = 1; /* -t implies -v */ 56 break; 57 case 'u': 58 setbuf(stdout, (char *)NULL); 59 break; 60 case 'v': 61 vflag = 1; 62 break; 63 case '?': 64 (void)fprintf(stderr, 65 "usage: cat [-benstuv] [-] [file ...]\n"); 66 exit(1); 67 } 68 argv += optind; 69 70 if (bflag || eflag || nflag || sflag || tflag || vflag) 71 cook_args(argv); 72 else 73 raw_args(argv); 74 exit(rval); 75 } 76 77 cook_args(argv) 78 char **argv; 79 { 80 register FILE *fp; 81 82 fp = stdin; 83 filename = "-"; 84 do { 85 if (*argv) { 86 if (!strcmp(*argv, "-")) 87 fp = stdin; 88 else if (!(fp = fopen(*argv, "r"))) { 89 (void)fprintf(stderr, 90 "cat: %s: %s\n", *argv, strerror(errno)); 91 rval = 1; 92 ++argv; 93 continue; 94 } 95 filename = *argv++; 96 } 97 cook_buf(fp); 98 if (fp != stdin) 99 (void)fclose(fp); 100 } while (*argv); 101 } 102 103 cook_buf(fp) 104 register FILE *fp; 105 { 106 register int ch, gobble, line, prev; 107 108 line = gobble = 0; 109 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 110 if (prev == '\n') { 111 if (ch == '\n') { 112 if (sflag) { 113 if (!gobble && putchar(ch) == EOF) 114 break; 115 gobble = 1; 116 continue; 117 } 118 if (nflag && !bflag) { 119 (void)fprintf(stdout, "%6d\t", ++line); 120 if (ferror(stdout)) 121 break; 122 } 123 } else if (nflag) { 124 (void)fprintf(stdout, "%6d\t", ++line); 125 if (ferror(stdout)) 126 break; 127 } 128 } 129 gobble = 0; 130 if (ch == '\n') { 131 if (eflag) 132 if (putchar('$') == EOF) 133 break; 134 } else if (ch == '\t') { 135 if (tflag) { 136 if (putchar('^') == EOF || putchar('I') == EOF) 137 break; 138 continue; 139 } 140 } else if (vflag) { 141 if (!isascii(ch)) { 142 if (putchar('M') == EOF || putchar('-') == EOF) 143 break; 144 ch = toascii(ch); 145 } 146 if (iscntrl(ch)) { 147 if (putchar('^') == EOF || 148 putchar(ch == '\177' ? '?' : 149 ch | 0100) == EOF) 150 break; 151 continue; 152 } 153 } 154 if (putchar(ch) == EOF) 155 break; 156 } 157 if (ferror(fp)) { 158 (void)fprintf(stderr, "cat: %s: read error\n", filename); 159 rval = 1; 160 } 161 if (ferror(stdout)) { 162 clearerr(stdout); 163 (void)fprintf(stderr, "cat: stdout: write error\n"); 164 rval = 1; 165 } 166 } 167 168 raw_args(argv) 169 char **argv; 170 { 171 register int fd; 172 173 fd = fileno(stdin); 174 filename = "-"; 175 do { 176 if (*argv) { 177 if (!strcmp(*argv, "-")) 178 fd = fileno(stdin); 179 else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 180 (void)fprintf(stderr, "cat: %s: %s\n", 181 *argv, strerror(errno)); 182 rval = 1; 183 ++argv; 184 continue; 185 } 186 filename = *argv++; 187 } 188 rval |= raw_cat(fd); 189 if (fd != fileno(stdin)) 190 (void)close(fd); 191 } while (*argv); 192 } 193 194 raw_cat(fd) 195 register int fd; 196 { 197 register int nr, nw, off; 198 static int bsize; 199 static char *buf; 200 struct stat sbuf; 201 char *malloc(), *strerror(); 202 203 if (!buf) { 204 if (fstat(fileno(stdout), &sbuf)) { 205 (void)fprintf(stderr, "cat: %s: %s\n", filename, 206 strerror(errno)); 207 return(1); 208 } 209 bsize = MAX(sbuf.st_blksize, 1024); 210 if (!(buf = malloc((u_int)bsize))) { 211 (void)fprintf(stderr, "cat: %s: no memory.\n", 212 filename); 213 return(1); 214 } 215 } 216 while ((nr = read(fd, buf, bsize)) > 0) 217 for (off = 0; off < nr; nr -= nw, off += nw) 218 if ((nw = write(fileno(stdout), buf + off, nr)) < 0) { 219 perror("cat: stdout"); 220 return(1); 221 } 222 if (nr < 0) { 223 (void)fprintf(stderr, "cat: %s: %s\n", filename, 224 strerror(errno)); 225 return(1); 226 } 227 return(0); 228 } 229