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.10 (Berkeley) 03/05/90"; 29 #endif /* not lint */ 30 31 #include <sys/param.h> 32 #include <sys/stat.h> 33 #include <sys/file.h> 34 #include <stdio.h> 35 #include <ctype.h> 36 37 extern int errno; 38 int bflag, eflag, nflag, sflag, tflag, vflag; 39 int rval; 40 char *filename; 41 42 main(argc, argv) 43 int argc; 44 char **argv; 45 { 46 extern int optind; 47 int ch; 48 char *strerror(); 49 50 while ((ch = getopt(argc, argv, "benstuv")) != EOF) 51 switch (ch) { 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 argv += optind; 79 80 if (bflag || eflag || nflag || sflag || tflag || vflag) 81 cook_args(argv); 82 else 83 raw_args(argv); 84 exit(rval); 85 } 86 87 cook_args(argv) 88 char **argv; 89 { 90 register FILE *fp; 91 92 fp = stdin; 93 filename = "-"; 94 do { 95 if (*argv) { 96 if (!strcmp(*argv, "-")) 97 fp = stdin; 98 else if (!(fp = fopen(*argv, "r"))) { 99 (void)fprintf(stderr, 100 "cat: %s: %s\n", *argv, strerror(errno)); 101 rval = 1; 102 ++argv; 103 continue; 104 } 105 filename = *argv++; 106 } 107 cook_buf(fp); 108 if (fp != stdin) 109 (void)fclose(fp); 110 } while (*argv); 111 } 112 113 cook_buf(fp) 114 register FILE *fp; 115 { 116 register int ch, gobble, line, prev; 117 118 line = gobble = 0; 119 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 120 if (prev == '\n') { 121 if (ch == '\n') { 122 if (sflag) { 123 if (!gobble && putchar(ch) == EOF) 124 break; 125 gobble = 1; 126 continue; 127 } 128 if (nflag && !bflag) { 129 (void)fprintf(stdout, "%6d\t", ++line); 130 if (ferror(stdout)) 131 break; 132 } 133 } else if (nflag) { 134 (void)fprintf(stdout, "%6d\t", ++line); 135 if (ferror(stdout)) 136 break; 137 } 138 } 139 gobble = 0; 140 if (ch == '\n') { 141 if (eflag) 142 if (putchar('$') == EOF) 143 break; 144 } else if (ch == '\t') { 145 if (tflag) { 146 if (putchar('^') == EOF || putchar('I') == EOF) 147 break; 148 continue; 149 } 150 } else if (vflag) { 151 if (!isascii(ch)) { 152 if (putchar('M') == EOF || putchar('-') == EOF) 153 break; 154 ch = toascii(ch); 155 } 156 if (iscntrl(ch)) { 157 if (putchar('^') == EOF || 158 putchar(ch == '\177' ? '?' : 159 ch | 0100) == EOF) 160 break; 161 continue; 162 } 163 } 164 if (putchar(ch) == EOF) 165 break; 166 } 167 if (ferror(fp)) { 168 (void)fprintf(stderr, "cat: %s: read error\n", filename); 169 rval = 1; 170 } 171 if (ferror(stdout)) { 172 clearerr(stdout); 173 (void)fprintf(stderr, "cat: stdout: write error\n"); 174 rval = 1; 175 } 176 } 177 178 raw_args(argv) 179 char **argv; 180 { 181 register int fd; 182 183 fd = fileno(stdin); 184 filename = "-"; 185 do { 186 if (*argv) { 187 if (!strcmp(*argv, "-")) 188 fd = fileno(stdin); 189 else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 190 (void)fprintf(stderr, "cat: %s: %s\n", 191 *argv, strerror(errno)); 192 rval = 1; 193 ++argv; 194 continue; 195 } 196 filename = *argv++; 197 } 198 rval |= raw_cat(fd); 199 if (fd != fileno(stdin)) 200 (void)close(fd); 201 } while (*argv); 202 } 203 204 raw_cat(fd) 205 register int fd; 206 { 207 register int nr, nw, off; 208 static int bsize; 209 static char *buf; 210 struct stat sbuf; 211 char *malloc(), *strerror(); 212 213 if (!buf) { 214 if (fstat(fileno(stdout), &sbuf)) { 215 (void)fprintf(stderr, "cat: %s: %s\n", filename, 216 strerror(errno)); 217 return(1); 218 } 219 bsize = MAX(sbuf.st_blksize, 1024); 220 if (!(buf = malloc((u_int)bsize))) { 221 (void)fprintf(stderr, "cat: %s: no memory.\n", 222 filename); 223 return(1); 224 } 225 } 226 while ((nr = read(fd, buf, bsize)) > 0) 227 for (off = 0; off < nr;) { 228 if ((nw = write(fileno(stdout), buf + off, nr)) < 0) { 229 perror("cat: stdout"); 230 return(1); 231 } 232 off += nw; 233 } 234 if (nr < 0) { 235 (void)fprintf(stderr, "cat: %s: %s\n", filename, 236 strerror(errno)); 237 return(1); 238 } 239 return(0); 240 } 241