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