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