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.13 (Berkeley) 05/02/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 exit(rval); 80 } 81 82 void 83 cook_args(argv) 84 char **argv; 85 { 86 register FILE *fp; 87 88 fp = stdin; 89 filename = "-"; 90 do { 91 if (*argv) { 92 if (!strcmp(*argv, "-")) 93 fp = stdin; 94 else if (!(fp = fopen(*argv, "r"))) { 95 err(0, "%s: %s", *argv, strerror(errno)); 96 ++argv; 97 continue; 98 } 99 filename = *argv++; 100 } 101 cook_buf(fp); 102 if (fp != stdin) 103 (void)fclose(fp); 104 } while (*argv); 105 } 106 107 void 108 cook_buf(fp) 109 register FILE *fp; 110 { 111 register int ch, gobble, line, prev; 112 113 line = gobble = 0; 114 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 115 if (prev == '\n') { 116 if (ch == '\n') { 117 if (sflag) { 118 if (!gobble && putchar(ch) == EOF) 119 break; 120 gobble = 1; 121 continue; 122 } 123 if (nflag && !bflag) { 124 (void)fprintf(stdout, "%6d\t", ++line); 125 if (ferror(stdout)) 126 break; 127 } 128 } else if (nflag) { 129 (void)fprintf(stdout, "%6d\t", ++line); 130 if (ferror(stdout)) 131 break; 132 } 133 } 134 gobble = 0; 135 if (ch == '\n') { 136 if (eflag) 137 if (putchar('$') == EOF) 138 break; 139 } else if (ch == '\t') { 140 if (tflag) { 141 if (putchar('^') == EOF || putchar('I') == EOF) 142 break; 143 continue; 144 } 145 } else if (vflag) { 146 if (!isascii(ch)) { 147 if (putchar('M') == EOF || putchar('-') == EOF) 148 break; 149 ch = toascii(ch); 150 } 151 if (iscntrl(ch)) { 152 if (putchar('^') == EOF || 153 putchar(ch == '\177' ? '?' : 154 ch | 0100) == EOF) 155 break; 156 continue; 157 } 158 } 159 if (putchar(ch) == EOF) 160 break; 161 } 162 if (ferror(fp)) { 163 err(0, "%s: %s", strerror(errno)); 164 clearerr(fp); 165 } 166 if (ferror(stdout)) 167 err(1, "stdout: %s", strerror(errno)); 168 } 169 170 void 171 raw_args(argv) 172 char **argv; 173 { 174 register int fd; 175 176 fd = fileno(stdin); 177 filename = "-"; 178 do { 179 if (*argv) { 180 if (!strcmp(*argv, "-")) 181 fd = fileno(stdin); 182 else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 183 err(0, "%s: %s", *argv, strerror(errno)); 184 ++argv; 185 continue; 186 } 187 filename = *argv++; 188 } 189 raw_cat(fd); 190 if (fd != fileno(stdin)) 191 (void)close(fd); 192 } while (*argv); 193 } 194 195 void 196 raw_cat(rfd) 197 register int rfd; 198 { 199 register int nr, nw, off, wfd; 200 static int bsize; 201 static char *buf; 202 struct stat sbuf; 203 204 wfd = fileno(stdout); 205 if (!buf) { 206 if (fstat(wfd, &sbuf)) 207 err(1, "%s: %s", filename, strerror(errno)); 208 bsize = MAX(sbuf.st_blksize, 1024); 209 if (!(buf = malloc((u_int)bsize))) 210 err(1, "%s", strerror(errno)); 211 } 212 while ((nr = read(rfd, buf, bsize)) > 0) 213 for (off = 0; off < nr; nr -= nw, off += nw) 214 if ((nw = write(wfd, buf + off, nr)) < 0) 215 err(1, "stdout"); 216 if (nr < 0) 217 err(0, "%s: %s", filename, strerror(errno)); 218 } 219 220 #if __STDC__ 221 #include <stdarg.h> 222 #else 223 #include <varargs.h> 224 #endif 225 226 void 227 #if __STDC__ 228 err(int ex, const char *fmt, ...) 229 #else 230 err(ex, fmt, va_alist) 231 int ex; 232 char *fmt; 233 va_dcl 234 #endif 235 { 236 va_list ap; 237 #if __STDC__ 238 va_start(ap, fmt); 239 #else 240 va_start(ap); 241 #endif 242 (void)fprintf(stderr, "cat: "); 243 (void)vfprintf(stderr, fmt, ap); 244 va_end(ap); 245 (void)fprintf(stderr, "\n"); 246 if (ex) 247 exit(1); 248 rval = 1; 249 } 250