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