cat.c revision 1556
11556Srgrimes/* 21556Srgrimes * Copyright (c) 1989, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Kevin Fall. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 351556Srgrimes */ 361556Srgrimes 371556Srgrimes#ifndef lint 381556Srgrimesstatic char copyright[] = 391556Srgrimes"@(#) Copyright (c) 1989, 1993\n\ 401556Srgrimes The Regents of the University of California. All rights reserved.\n"; 411556Srgrimes#endif /* not lint */ 421556Srgrimes 431556Srgrimes#ifndef lint 441556Srgrimesstatic char sccsid[] = "@(#)cat.c 8.1 (Berkeley) 7/19/93"; 451556Srgrimes#endif /* not lint */ 461556Srgrimes 471556Srgrimes#include <sys/param.h> 481556Srgrimes#include <sys/stat.h> 491556Srgrimes 501556Srgrimes#include <ctype.h> 511556Srgrimes#include <err.h> 521556Srgrimes#include <errno.h> 531556Srgrimes#include <fcntl.h> 541556Srgrimes#include <stdio.h> 551556Srgrimes#include <stdlib.h> 561556Srgrimes#include <string.h> 571556Srgrimes#include <unistd.h> 581556Srgrimes 591556Srgrimesint bflag, eflag, nflag, sflag, tflag, vflag; 601556Srgrimesint rval; 611556Srgrimeschar *filename; 621556Srgrimes 631556Srgrimesvoid cook_args __P((char *argv[])); 641556Srgrimesvoid cook_buf __P((FILE *)); 651556Srgrimesvoid raw_args __P((char *argv[])); 661556Srgrimesvoid raw_cat __P((int)); 671556Srgrimes 681556Srgrimesint 691556Srgrimesmain(argc, argv) 701556Srgrimes int argc; 711556Srgrimes char *argv[]; 721556Srgrimes{ 731556Srgrimes extern int optind; 741556Srgrimes int ch; 751556Srgrimes 761556Srgrimes while ((ch = getopt(argc, argv, "benstuv")) != EOF) 771556Srgrimes switch (ch) { 781556Srgrimes case 'b': 791556Srgrimes bflag = nflag = 1; /* -b implies -n */ 801556Srgrimes break; 811556Srgrimes case 'e': 821556Srgrimes eflag = vflag = 1; /* -e implies -v */ 831556Srgrimes break; 841556Srgrimes case 'n': 851556Srgrimes nflag = 1; 861556Srgrimes break; 871556Srgrimes case 's': 881556Srgrimes sflag = 1; 891556Srgrimes break; 901556Srgrimes case 't': 911556Srgrimes tflag = vflag = 1; /* -t implies -v */ 921556Srgrimes break; 931556Srgrimes case 'u': 941556Srgrimes setbuf(stdout, (char *)NULL); 951556Srgrimes break; 961556Srgrimes case 'v': 971556Srgrimes vflag = 1; 981556Srgrimes break; 991556Srgrimes case '?': 1001556Srgrimes (void)fprintf(stderr, 1011556Srgrimes "usage: cat [-benstuv] [-] [file ...]\n"); 1021556Srgrimes exit(1); 1031556Srgrimes } 1041556Srgrimes argv += optind; 1051556Srgrimes 1061556Srgrimes if (bflag || eflag || nflag || sflag || tflag || vflag) 1071556Srgrimes cook_args(argv); 1081556Srgrimes else 1091556Srgrimes raw_args(argv); 1101556Srgrimes if (fclose(stdout)) 1111556Srgrimes err(1, "stdout"); 1121556Srgrimes exit(rval); 1131556Srgrimes} 1141556Srgrimes 1151556Srgrimesvoid 1161556Srgrimescook_args(argv) 1171556Srgrimes char **argv; 1181556Srgrimes{ 1191556Srgrimes register FILE *fp; 1201556Srgrimes 1211556Srgrimes fp = stdin; 1221556Srgrimes filename = "stdin"; 1231556Srgrimes do { 1241556Srgrimes if (*argv) { 1251556Srgrimes if (!strcmp(*argv, "-")) 1261556Srgrimes fp = stdin; 1271556Srgrimes else if ((fp = fopen(*argv, "r")) == NULL) { 1281556Srgrimes warn("%s", *argv); 1291556Srgrimes ++argv; 1301556Srgrimes continue; 1311556Srgrimes } 1321556Srgrimes filename = *argv++; 1331556Srgrimes } 1341556Srgrimes cook_buf(fp); 1351556Srgrimes if (fp != stdin) 1361556Srgrimes (void)fclose(fp); 1371556Srgrimes } while (*argv); 1381556Srgrimes} 1391556Srgrimes 1401556Srgrimesvoid 1411556Srgrimescook_buf(fp) 1421556Srgrimes register FILE *fp; 1431556Srgrimes{ 1441556Srgrimes register int ch, gobble, line, prev; 1451556Srgrimes 1461556Srgrimes line = gobble = 0; 1471556Srgrimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 1481556Srgrimes if (prev == '\n') { 1491556Srgrimes if (ch == '\n') { 1501556Srgrimes if (sflag) { 1511556Srgrimes if (!gobble && putchar(ch) == EOF) 1521556Srgrimes break; 1531556Srgrimes gobble = 1; 1541556Srgrimes continue; 1551556Srgrimes } 1561556Srgrimes if (nflag && !bflag) { 1571556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1581556Srgrimes if (ferror(stdout)) 1591556Srgrimes break; 1601556Srgrimes } 1611556Srgrimes } else if (nflag) { 1621556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1631556Srgrimes if (ferror(stdout)) 1641556Srgrimes break; 1651556Srgrimes } 1661556Srgrimes } 1671556Srgrimes gobble = 0; 1681556Srgrimes if (ch == '\n') { 1691556Srgrimes if (eflag) 1701556Srgrimes if (putchar('$') == EOF) 1711556Srgrimes break; 1721556Srgrimes } else if (ch == '\t') { 1731556Srgrimes if (tflag) { 1741556Srgrimes if (putchar('^') == EOF || putchar('I') == EOF) 1751556Srgrimes break; 1761556Srgrimes continue; 1771556Srgrimes } 1781556Srgrimes } else if (vflag) { 1791556Srgrimes if (!isascii(ch)) { 1801556Srgrimes if (putchar('M') == EOF || putchar('-') == EOF) 1811556Srgrimes break; 1821556Srgrimes ch = toascii(ch); 1831556Srgrimes } 1841556Srgrimes if (iscntrl(ch)) { 1851556Srgrimes if (putchar('^') == EOF || 1861556Srgrimes putchar(ch == '\177' ? '?' : 1871556Srgrimes ch | 0100) == EOF) 1881556Srgrimes break; 1891556Srgrimes continue; 1901556Srgrimes } 1911556Srgrimes } 1921556Srgrimes if (putchar(ch) == EOF) 1931556Srgrimes break; 1941556Srgrimes } 1951556Srgrimes if (ferror(fp)) { 1961556Srgrimes warn("%s", filename); 1971556Srgrimes clearerr(fp); 1981556Srgrimes } 1991556Srgrimes if (ferror(stdout)) 2001556Srgrimes err(1, "stdout"); 2011556Srgrimes} 2021556Srgrimes 2031556Srgrimesvoid 2041556Srgrimesraw_args(argv) 2051556Srgrimes char **argv; 2061556Srgrimes{ 2071556Srgrimes register int fd; 2081556Srgrimes 2091556Srgrimes fd = fileno(stdin); 2101556Srgrimes filename = "stdin"; 2111556Srgrimes do { 2121556Srgrimes if (*argv) { 2131556Srgrimes if (!strcmp(*argv, "-")) 2141556Srgrimes fd = fileno(stdin); 2151556Srgrimes else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 2161556Srgrimes warn("%s", *argv); 2171556Srgrimes ++argv; 2181556Srgrimes continue; 2191556Srgrimes } 2201556Srgrimes filename = *argv++; 2211556Srgrimes } 2221556Srgrimes raw_cat(fd); 2231556Srgrimes if (fd != fileno(stdin)) 2241556Srgrimes (void)close(fd); 2251556Srgrimes } while (*argv); 2261556Srgrimes} 2271556Srgrimes 2281556Srgrimesvoid 2291556Srgrimesraw_cat(rfd) 2301556Srgrimes register int rfd; 2311556Srgrimes{ 2321556Srgrimes register int nr, nw, off, wfd; 2331556Srgrimes static int bsize; 2341556Srgrimes static char *buf; 2351556Srgrimes struct stat sbuf; 2361556Srgrimes 2371556Srgrimes wfd = fileno(stdout); 2381556Srgrimes if (buf == NULL) { 2391556Srgrimes if (fstat(wfd, &sbuf)) 2401556Srgrimes err(1, "%s", filename); 2411556Srgrimes bsize = MAX(sbuf.st_blksize, 1024); 2421556Srgrimes if ((buf = malloc((u_int)bsize)) == NULL) 2431556Srgrimes err(1, ""); 2441556Srgrimes } 2451556Srgrimes while ((nr = read(rfd, buf, bsize)) > 0) 2461556Srgrimes for (off = 0; nr; nr -= nw, off += nw) 2471556Srgrimes if ((nw = write(wfd, buf + off, nr)) < 0) 2481556Srgrimes err(1, "stdout"); 2491556Srgrimes if (nr < 0) 2501556Srgrimes warn("%s", filename); 2511556Srgrimes} 252