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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 static char copyright[] = 39 "@(#) Copyright (c) 1989, 1993\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41 #endif /* not lint */ 42 43 #ifndef lint 44 /*static char sccsid[] = "from: @(#)cat.c 8.1 (Berkeley) 7/19/93";*/ 45 static char *rcsid = "$Id: cat.c,v 1.9 1994/09/20 01:24:11 mycroft Exp $"; 46 #endif /* not lint */ 47 48 #include <sys/param.h> 49 #include <sys/stat.h> 50 51 #include <locale.h> 52 #include <ctype.h> 53 #include <err.h> 54 #include <errno.h> 55 #include <fcntl.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 #include <unistd.h> 60 61 int bflag, eflag, nflag, sflag, tflag, vflag; 62 int rval; 63 char *filename; 64 65 void cook_args __P((char *argv[])); 66 void cook_buf __P((FILE *)); 67 void raw_args __P((char *argv[])); 68 void raw_cat __P((int)); 69 70 int 71 main(argc, argv) 72 int argc; 73 char *argv[]; 74 { 75 extern int optind; 76 int ch; 77 78 setlocale(LC_ALL, ""); 79 80 while ((ch = getopt(argc, argv, "benstuv")) != -1) 81 switch (ch) { 82 case 'b': 83 bflag = nflag = 1; /* -b implies -n */ 84 break; 85 case 'e': 86 eflag = vflag = 1; /* -e implies -v */ 87 break; 88 case 'n': 89 nflag = 1; 90 break; 91 case 's': 92 sflag = 1; 93 break; 94 case 't': 95 tflag = vflag = 1; /* -t implies -v */ 96 break; 97 case 'u': 98 setbuf(stdout, (char *)NULL); 99 break; 100 case 'v': 101 vflag = 1; 102 break; 103 default: 104 case '?': 105 (void)fprintf(stderr, 106 "usage: cat [-benstuv] [-] [file ...]\n"); 107 exit(1); 108 } 109 argv += optind; 110 111 if (bflag || eflag || nflag || sflag || tflag || vflag) 112 cook_args(argv); 113 else 114 raw_args(argv); 115 if (fclose(stdout)) 116 err(1, "stdout"); 117 exit(rval); 118 } 119 120 void 121 cook_args(argv) 122 char **argv; 123 { 124 register FILE *fp; 125 126 fp = stdin; 127 filename = "stdin"; 128 do { 129 if (*argv) { 130 if (!strcmp(*argv, "-")) 131 fp = stdin; 132 else if ((fp = fopen(*argv, "r")) == NULL) { 133 warn("%s", *argv); 134 ++argv; 135 continue; 136 } 137 filename = *argv++; 138 } 139 cook_buf(fp); 140 if (fp != stdin) 141 (void)fclose(fp); 142 } while (*argv); 143 } 144 145 void 146 cook_buf(fp) 147 register FILE *fp; 148 { 149 register int ch, gobble, line, prev; 150 151 line = gobble = 0; 152 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 153 if (prev == '\n') { 154 if (ch == '\n') { 155 if (sflag) { 156 if (!gobble && putchar(ch) == EOF) 157 break; 158 gobble = 1; 159 continue; 160 } 161 if (nflag && !bflag) { 162 (void)fprintf(stdout, "%6d\t", ++line); 163 if (ferror(stdout)) 164 break; 165 } 166 } else if (nflag) { 167 (void)fprintf(stdout, "%6d\t", ++line); 168 if (ferror(stdout)) 169 break; 170 } 171 } 172 gobble = 0; 173 if (ch == '\n') { 174 if (eflag) 175 if (putchar('$') == EOF) 176 break; 177 } else if (ch == '\t') { 178 if (tflag) { 179 if (putchar('^') == EOF || putchar('I') == EOF) 180 break; 181 continue; 182 } 183 } else if (vflag) { 184 if (!isascii(ch)) { 185 if (putchar('M') == EOF || putchar('-') == EOF) 186 break; 187 ch = toascii(ch); 188 } 189 if (iscntrl(ch)) { 190 if (putchar('^') == EOF || 191 putchar(ch == '\177' ? '?' : 192 ch | 0100) == EOF) 193 break; 194 continue; 195 } 196 } 197 if (putchar(ch) == EOF) 198 break; 199 } 200 if (ferror(fp)) { 201 warn("%s", filename); 202 clearerr(fp); 203 } 204 if (ferror(stdout)) 205 err(1, "stdout"); 206 } 207 208 void 209 raw_args(argv) 210 char **argv; 211 { 212 register int fd; 213 214 fd = fileno(stdin); 215 filename = "stdin"; 216 do { 217 if (*argv) { 218 if (!strcmp(*argv, "-")) 219 fd = fileno(stdin); 220 else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 221 warn("%s", *argv); 222 ++argv; 223 continue; 224 } 225 filename = *argv++; 226 } 227 raw_cat(fd); 228 if (fd != fileno(stdin)) 229 (void)close(fd); 230 } while (*argv); 231 } 232 233 void 234 raw_cat(rfd) 235 register int rfd; 236 { 237 register int nr, nw, off, wfd; 238 static int bsize; 239 static char *buf; 240 struct stat sbuf; 241 242 wfd = fileno(stdout); 243 if (buf == NULL) { 244 if (fstat(wfd, &sbuf)) 245 err(1, "%s", filename); 246 bsize = MAX(sbuf.st_blksize, 1024); 247 if ((buf = malloc((u_int)bsize)) == NULL) 248 err(1, NULL); 249 } 250 while ((nr = read(rfd, buf, bsize)) > 0) 251 for (off = 0; nr; nr -= nw, off += nw) 252 if ((nw = write(wfd, buf + off, nr)) < 0) 253 err(1, "stdout"); 254 if (nr < 0) 255 warn("%s", filename); 256 } 257