1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. 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 static char copyright[] = 13 "@(#) Copyright (c) 1989, 1993\n\ 14 The Regents of the University of California. All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 04/27/95"; 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")) != -1) 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 default: 74 case '?': 75 (void)fprintf(stderr, 76 "usage: cat [-benstuv] [-] [file ...]\n"); 77 exit(1); 78 } 79 argv += optind; 80 81 if (bflag || eflag || nflag || sflag || tflag || vflag) 82 cook_args(argv); 83 else 84 raw_args(argv); 85 if (fclose(stdout)) 86 err(1, "stdout"); 87 exit(rval); 88 } 89 90 void 91 cook_args(argv) 92 char **argv; 93 { 94 register FILE *fp; 95 96 fp = stdin; 97 filename = "stdin"; 98 do { 99 if (*argv) { 100 if (!strcmp(*argv, "-")) 101 fp = stdin; 102 else if ((fp = fopen(*argv, "r")) == NULL) { 103 warn("%s", *argv); 104 ++argv; 105 continue; 106 } 107 filename = *argv++; 108 } 109 cook_buf(fp); 110 if (fp != stdin) 111 (void)fclose(fp); 112 } while (*argv); 113 } 114 115 void 116 cook_buf(fp) 117 register FILE *fp; 118 { 119 register int ch, gobble, line, prev; 120 121 line = gobble = 0; 122 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 123 if (prev == '\n') { 124 if (ch == '\n') { 125 if (sflag) { 126 if (!gobble && putchar(ch) == EOF) 127 break; 128 gobble = 1; 129 continue; 130 } 131 if (nflag && !bflag) { 132 (void)fprintf(stdout, "%6d\t", ++line); 133 if (ferror(stdout)) 134 break; 135 } 136 } else if (nflag) { 137 (void)fprintf(stdout, "%6d\t", ++line); 138 if (ferror(stdout)) 139 break; 140 } 141 } 142 gobble = 0; 143 if (ch == '\n') { 144 if (eflag) 145 if (putchar('$') == EOF) 146 break; 147 } else if (ch == '\t') { 148 if (tflag) { 149 if (putchar('^') == EOF || putchar('I') == EOF) 150 break; 151 continue; 152 } 153 } else if (vflag) { 154 if (!isascii(ch)) { 155 if (putchar('M') == EOF || putchar('-') == EOF) 156 break; 157 ch = toascii(ch); 158 } 159 if (iscntrl(ch)) { 160 if (putchar('^') == EOF || 161 putchar(ch == '\177' ? '?' : 162 ch | 0100) == EOF) 163 break; 164 continue; 165 } 166 } 167 if (putchar(ch) == EOF) 168 break; 169 } 170 if (ferror(fp)) { 171 warn("%s", filename); 172 clearerr(fp); 173 } 174 if (ferror(stdout)) 175 err(1, "stdout"); 176 } 177 178 void 179 raw_args(argv) 180 char **argv; 181 { 182 register int fd; 183 184 fd = fileno(stdin); 185 filename = "stdin"; 186 do { 187 if (*argv) { 188 if (!strcmp(*argv, "-")) 189 fd = fileno(stdin); 190 else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 191 warn("%s", *argv); 192 ++argv; 193 continue; 194 } 195 filename = *argv++; 196 } 197 raw_cat(fd); 198 if (fd != fileno(stdin)) 199 (void)close(fd); 200 } while (*argv); 201 } 202 203 void 204 raw_cat(rfd) 205 register int rfd; 206 { 207 register int nr, nw, off, wfd; 208 static int bsize; 209 static char *buf; 210 struct stat sbuf; 211 212 wfd = fileno(stdout); 213 if (buf == NULL) { 214 if (fstat(wfd, &sbuf)) 215 err(1, "%s", filename); 216 bsize = MAX(sbuf.st_blksize, 1024); 217 if ((buf = malloc((u_int)bsize)) == NULL) 218 err(1, NULL); 219 } 220 while ((nr = read(rfd, buf, bsize)) > 0) 221 for (off = 0; nr; nr -= nw, off += nw) 222 if ((nw = write(wfd, buf + off, nr)) < 0) 223 err(1, "stdout"); 224 if (nr < 0) 225 warn("%s", filename); 226 } 227