cat.c revision 18578
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. 353044Sdg * 3618578Sache * $Id: cat.c,v 1.4 1996/09/28 21:19:27 imp Exp $ 371556Srgrimes */ 381556Srgrimes 391556Srgrimes#ifndef lint 401556Srgrimesstatic char copyright[] = 411556Srgrimes"@(#) Copyright (c) 1989, 1993\n\ 421556Srgrimes The Regents of the University of California. All rights reserved.\n"; 431556Srgrimes#endif /* not lint */ 441556Srgrimes 451556Srgrimes#ifndef lint 4618546Simpstatic char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; 471556Srgrimes#endif /* not lint */ 481556Srgrimes 491556Srgrimes#include <sys/param.h> 501556Srgrimes#include <sys/stat.h> 511556Srgrimes 521556Srgrimes#include <ctype.h> 531556Srgrimes#include <err.h> 541556Srgrimes#include <errno.h> 551556Srgrimes#include <fcntl.h> 5618578Sache#include <locale.h> 571556Srgrimes#include <stdio.h> 581556Srgrimes#include <stdlib.h> 591556Srgrimes#include <string.h> 601556Srgrimes#include <unistd.h> 611556Srgrimes 621556Srgrimesint bflag, eflag, nflag, sflag, tflag, vflag; 631556Srgrimesint rval; 641556Srgrimeschar *filename; 651556Srgrimes 661556Srgrimesvoid cook_args __P((char *argv[])); 671556Srgrimesvoid cook_buf __P((FILE *)); 681556Srgrimesvoid raw_args __P((char *argv[])); 691556Srgrimesvoid raw_cat __P((int)); 701556Srgrimes 711556Srgrimesint 721556Srgrimesmain(argc, argv) 731556Srgrimes int argc; 741556Srgrimes char *argv[]; 751556Srgrimes{ 761556Srgrimes extern int optind; 771556Srgrimes int ch; 781556Srgrimes 7918578Sache setlocale(LC_CTYPE, ""); 8018578Sache 811556Srgrimes while ((ch = getopt(argc, argv, "benstuv")) != EOF) 821556Srgrimes switch (ch) { 831556Srgrimes case 'b': 841556Srgrimes bflag = nflag = 1; /* -b implies -n */ 851556Srgrimes break; 861556Srgrimes case 'e': 871556Srgrimes eflag = vflag = 1; /* -e implies -v */ 881556Srgrimes break; 891556Srgrimes case 'n': 901556Srgrimes nflag = 1; 911556Srgrimes break; 921556Srgrimes case 's': 931556Srgrimes sflag = 1; 941556Srgrimes break; 951556Srgrimes case 't': 961556Srgrimes tflag = vflag = 1; /* -t implies -v */ 971556Srgrimes break; 981556Srgrimes case 'u': 991556Srgrimes setbuf(stdout, (char *)NULL); 1001556Srgrimes break; 1011556Srgrimes case 'v': 1021556Srgrimes vflag = 1; 1031556Srgrimes break; 10418546Simp default: 1051556Srgrimes (void)fprintf(stderr, 1061556Srgrimes "usage: cat [-benstuv] [-] [file ...]\n"); 1071556Srgrimes exit(1); 1081556Srgrimes } 1091556Srgrimes argv += optind; 1101556Srgrimes 1111556Srgrimes if (bflag || eflag || nflag || sflag || tflag || vflag) 1121556Srgrimes cook_args(argv); 1131556Srgrimes else 1141556Srgrimes raw_args(argv); 1151556Srgrimes if (fclose(stdout)) 1161556Srgrimes err(1, "stdout"); 1171556Srgrimes exit(rval); 1181556Srgrimes} 1191556Srgrimes 1201556Srgrimesvoid 1211556Srgrimescook_args(argv) 1221556Srgrimes char **argv; 1231556Srgrimes{ 1241556Srgrimes register FILE *fp; 1251556Srgrimes 1261556Srgrimes fp = stdin; 1271556Srgrimes filename = "stdin"; 1281556Srgrimes do { 1291556Srgrimes if (*argv) { 1301556Srgrimes if (!strcmp(*argv, "-")) 1311556Srgrimes fp = stdin; 1321556Srgrimes else if ((fp = fopen(*argv, "r")) == NULL) { 1331556Srgrimes warn("%s", *argv); 13411145Sbde rval = 1; 1351556Srgrimes ++argv; 1361556Srgrimes continue; 1371556Srgrimes } 1381556Srgrimes filename = *argv++; 1391556Srgrimes } 1401556Srgrimes cook_buf(fp); 1411556Srgrimes if (fp != stdin) 1421556Srgrimes (void)fclose(fp); 1431556Srgrimes } while (*argv); 1441556Srgrimes} 1451556Srgrimes 1461556Srgrimesvoid 1471556Srgrimescook_buf(fp) 1481556Srgrimes register FILE *fp; 1491556Srgrimes{ 1501556Srgrimes register int ch, gobble, line, prev; 1511556Srgrimes 1521556Srgrimes line = gobble = 0; 1531556Srgrimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 1541556Srgrimes if (prev == '\n') { 1551556Srgrimes if (ch == '\n') { 1561556Srgrimes if (sflag) { 1571556Srgrimes if (!gobble && putchar(ch) == EOF) 1581556Srgrimes break; 1591556Srgrimes gobble = 1; 1601556Srgrimes continue; 1611556Srgrimes } 1621556Srgrimes if (nflag && !bflag) { 1631556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1641556Srgrimes if (ferror(stdout)) 1651556Srgrimes break; 1661556Srgrimes } 1671556Srgrimes } else if (nflag) { 1681556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1691556Srgrimes if (ferror(stdout)) 1701556Srgrimes break; 1711556Srgrimes } 1721556Srgrimes } 1731556Srgrimes gobble = 0; 1741556Srgrimes if (ch == '\n') { 1751556Srgrimes if (eflag) 1761556Srgrimes if (putchar('$') == EOF) 1771556Srgrimes break; 1781556Srgrimes } else if (ch == '\t') { 1791556Srgrimes if (tflag) { 1801556Srgrimes if (putchar('^') == EOF || putchar('I') == EOF) 1811556Srgrimes break; 1821556Srgrimes continue; 1831556Srgrimes } 1841556Srgrimes } else if (vflag) { 18518578Sache if (!isascii(ch) && !isprint(ch)) { 1861556Srgrimes if (putchar('M') == EOF || putchar('-') == EOF) 1871556Srgrimes break; 1881556Srgrimes ch = toascii(ch); 1891556Srgrimes } 1901556Srgrimes if (iscntrl(ch)) { 1911556Srgrimes if (putchar('^') == EOF || 1921556Srgrimes putchar(ch == '\177' ? '?' : 1931556Srgrimes ch | 0100) == EOF) 1941556Srgrimes break; 1951556Srgrimes continue; 1961556Srgrimes } 1971556Srgrimes } 1981556Srgrimes if (putchar(ch) == EOF) 1991556Srgrimes break; 2001556Srgrimes } 2011556Srgrimes if (ferror(fp)) { 2021556Srgrimes warn("%s", filename); 20311145Sbde rval = 1; 2041556Srgrimes clearerr(fp); 2051556Srgrimes } 2061556Srgrimes if (ferror(stdout)) 2071556Srgrimes err(1, "stdout"); 2081556Srgrimes} 2091556Srgrimes 2101556Srgrimesvoid 2111556Srgrimesraw_args(argv) 2121556Srgrimes char **argv; 2131556Srgrimes{ 2141556Srgrimes register int fd; 2151556Srgrimes 2161556Srgrimes fd = fileno(stdin); 2171556Srgrimes filename = "stdin"; 2181556Srgrimes do { 2191556Srgrimes if (*argv) { 2201556Srgrimes if (!strcmp(*argv, "-")) 2211556Srgrimes fd = fileno(stdin); 2221556Srgrimes else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 2231556Srgrimes warn("%s", *argv); 22411145Sbde rval = 1; 2251556Srgrimes ++argv; 2261556Srgrimes continue; 2271556Srgrimes } 2281556Srgrimes filename = *argv++; 2291556Srgrimes } 2301556Srgrimes raw_cat(fd); 2311556Srgrimes if (fd != fileno(stdin)) 2321556Srgrimes (void)close(fd); 2331556Srgrimes } while (*argv); 2341556Srgrimes} 2351556Srgrimes 2361556Srgrimesvoid 2371556Srgrimesraw_cat(rfd) 2381556Srgrimes register int rfd; 2391556Srgrimes{ 2401556Srgrimes register int nr, nw, off, wfd; 2411556Srgrimes static int bsize; 2421556Srgrimes static char *buf; 2431556Srgrimes struct stat sbuf; 2441556Srgrimes 2451556Srgrimes wfd = fileno(stdout); 2461556Srgrimes if (buf == NULL) { 2471556Srgrimes if (fstat(wfd, &sbuf)) 2481556Srgrimes err(1, "%s", filename); 2491556Srgrimes bsize = MAX(sbuf.st_blksize, 1024); 2501556Srgrimes if ((buf = malloc((u_int)bsize)) == NULL) 25118546Simp err(1, NULL); 2521556Srgrimes } 2531556Srgrimes while ((nr = read(rfd, buf, bsize)) > 0) 2541556Srgrimes for (off = 0; nr; nr -= nw, off += nw) 2551556Srgrimes if ((nw = write(wfd, buf + off, nr)) < 0) 2561556Srgrimes err(1, "stdout"); 25711145Sbde if (nr < 0) { 2581556Srgrimes warn("%s", filename); 25911145Sbde rval = 1; 26011145Sbde } 2611556Srgrimes} 262