cat.c revision 18546
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 * 3618546Simp * $Id: cat.c,v 1.3 1995/10/03 12:46:37 bde 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> 561556Srgrimes#include <stdio.h> 571556Srgrimes#include <stdlib.h> 581556Srgrimes#include <string.h> 591556Srgrimes#include <unistd.h> 601556Srgrimes 611556Srgrimesint bflag, eflag, nflag, sflag, tflag, vflag; 621556Srgrimesint rval; 631556Srgrimeschar *filename; 641556Srgrimes 651556Srgrimesvoid cook_args __P((char *argv[])); 661556Srgrimesvoid cook_buf __P((FILE *)); 671556Srgrimesvoid raw_args __P((char *argv[])); 681556Srgrimesvoid raw_cat __P((int)); 691556Srgrimes 701556Srgrimesint 711556Srgrimesmain(argc, argv) 721556Srgrimes int argc; 731556Srgrimes char *argv[]; 741556Srgrimes{ 751556Srgrimes extern int optind; 761556Srgrimes int ch; 771556Srgrimes 781556Srgrimes while ((ch = getopt(argc, argv, "benstuv")) != EOF) 791556Srgrimes switch (ch) { 801556Srgrimes case 'b': 811556Srgrimes bflag = nflag = 1; /* -b implies -n */ 821556Srgrimes break; 831556Srgrimes case 'e': 841556Srgrimes eflag = vflag = 1; /* -e implies -v */ 851556Srgrimes break; 861556Srgrimes case 'n': 871556Srgrimes nflag = 1; 881556Srgrimes break; 891556Srgrimes case 's': 901556Srgrimes sflag = 1; 911556Srgrimes break; 921556Srgrimes case 't': 931556Srgrimes tflag = vflag = 1; /* -t implies -v */ 941556Srgrimes break; 951556Srgrimes case 'u': 961556Srgrimes setbuf(stdout, (char *)NULL); 971556Srgrimes break; 981556Srgrimes case 'v': 991556Srgrimes vflag = 1; 1001556Srgrimes break; 10118546Simp default: 1021556Srgrimes (void)fprintf(stderr, 1031556Srgrimes "usage: cat [-benstuv] [-] [file ...]\n"); 1041556Srgrimes exit(1); 1051556Srgrimes } 1061556Srgrimes argv += optind; 1071556Srgrimes 1081556Srgrimes if (bflag || eflag || nflag || sflag || tflag || vflag) 1091556Srgrimes cook_args(argv); 1101556Srgrimes else 1111556Srgrimes raw_args(argv); 1121556Srgrimes if (fclose(stdout)) 1131556Srgrimes err(1, "stdout"); 1141556Srgrimes exit(rval); 1151556Srgrimes} 1161556Srgrimes 1171556Srgrimesvoid 1181556Srgrimescook_args(argv) 1191556Srgrimes char **argv; 1201556Srgrimes{ 1211556Srgrimes register FILE *fp; 1221556Srgrimes 1231556Srgrimes fp = stdin; 1241556Srgrimes filename = "stdin"; 1251556Srgrimes do { 1261556Srgrimes if (*argv) { 1271556Srgrimes if (!strcmp(*argv, "-")) 1281556Srgrimes fp = stdin; 1291556Srgrimes else if ((fp = fopen(*argv, "r")) == NULL) { 1301556Srgrimes warn("%s", *argv); 13111145Sbde rval = 1; 1321556Srgrimes ++argv; 1331556Srgrimes continue; 1341556Srgrimes } 1351556Srgrimes filename = *argv++; 1361556Srgrimes } 1371556Srgrimes cook_buf(fp); 1381556Srgrimes if (fp != stdin) 1391556Srgrimes (void)fclose(fp); 1401556Srgrimes } while (*argv); 1411556Srgrimes} 1421556Srgrimes 1431556Srgrimesvoid 1441556Srgrimescook_buf(fp) 1451556Srgrimes register FILE *fp; 1461556Srgrimes{ 1471556Srgrimes register int ch, gobble, line, prev; 1481556Srgrimes 1491556Srgrimes line = gobble = 0; 1501556Srgrimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 1511556Srgrimes if (prev == '\n') { 1521556Srgrimes if (ch == '\n') { 1531556Srgrimes if (sflag) { 1541556Srgrimes if (!gobble && putchar(ch) == EOF) 1551556Srgrimes break; 1561556Srgrimes gobble = 1; 1571556Srgrimes continue; 1581556Srgrimes } 1591556Srgrimes if (nflag && !bflag) { 1601556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1611556Srgrimes if (ferror(stdout)) 1621556Srgrimes break; 1631556Srgrimes } 1641556Srgrimes } else if (nflag) { 1651556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1661556Srgrimes if (ferror(stdout)) 1671556Srgrimes break; 1681556Srgrimes } 1691556Srgrimes } 1701556Srgrimes gobble = 0; 1711556Srgrimes if (ch == '\n') { 1721556Srgrimes if (eflag) 1731556Srgrimes if (putchar('$') == EOF) 1741556Srgrimes break; 1751556Srgrimes } else if (ch == '\t') { 1761556Srgrimes if (tflag) { 1771556Srgrimes if (putchar('^') == EOF || putchar('I') == EOF) 1781556Srgrimes break; 1791556Srgrimes continue; 1801556Srgrimes } 1811556Srgrimes } else if (vflag) { 1821556Srgrimes if (!isascii(ch)) { 1831556Srgrimes if (putchar('M') == EOF || putchar('-') == EOF) 1841556Srgrimes break; 1851556Srgrimes ch = toascii(ch); 1861556Srgrimes } 1871556Srgrimes if (iscntrl(ch)) { 1881556Srgrimes if (putchar('^') == EOF || 1891556Srgrimes putchar(ch == '\177' ? '?' : 1901556Srgrimes ch | 0100) == EOF) 1911556Srgrimes break; 1921556Srgrimes continue; 1931556Srgrimes } 1941556Srgrimes } 1951556Srgrimes if (putchar(ch) == EOF) 1961556Srgrimes break; 1971556Srgrimes } 1981556Srgrimes if (ferror(fp)) { 1991556Srgrimes warn("%s", filename); 20011145Sbde rval = 1; 2011556Srgrimes clearerr(fp); 2021556Srgrimes } 2031556Srgrimes if (ferror(stdout)) 2041556Srgrimes err(1, "stdout"); 2051556Srgrimes} 2061556Srgrimes 2071556Srgrimesvoid 2081556Srgrimesraw_args(argv) 2091556Srgrimes char **argv; 2101556Srgrimes{ 2111556Srgrimes register int fd; 2121556Srgrimes 2131556Srgrimes fd = fileno(stdin); 2141556Srgrimes filename = "stdin"; 2151556Srgrimes do { 2161556Srgrimes if (*argv) { 2171556Srgrimes if (!strcmp(*argv, "-")) 2181556Srgrimes fd = fileno(stdin); 2191556Srgrimes else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 2201556Srgrimes warn("%s", *argv); 22111145Sbde rval = 1; 2221556Srgrimes ++argv; 2231556Srgrimes continue; 2241556Srgrimes } 2251556Srgrimes filename = *argv++; 2261556Srgrimes } 2271556Srgrimes raw_cat(fd); 2281556Srgrimes if (fd != fileno(stdin)) 2291556Srgrimes (void)close(fd); 2301556Srgrimes } while (*argv); 2311556Srgrimes} 2321556Srgrimes 2331556Srgrimesvoid 2341556Srgrimesraw_cat(rfd) 2351556Srgrimes register int rfd; 2361556Srgrimes{ 2371556Srgrimes register int nr, nw, off, wfd; 2381556Srgrimes static int bsize; 2391556Srgrimes static char *buf; 2401556Srgrimes struct stat sbuf; 2411556Srgrimes 2421556Srgrimes wfd = fileno(stdout); 2431556Srgrimes if (buf == NULL) { 2441556Srgrimes if (fstat(wfd, &sbuf)) 2451556Srgrimes err(1, "%s", filename); 2461556Srgrimes bsize = MAX(sbuf.st_blksize, 1024); 2471556Srgrimes if ((buf = malloc((u_int)bsize)) == NULL) 24818546Simp err(1, NULL); 2491556Srgrimes } 2501556Srgrimes while ((nr = read(rfd, buf, bsize)) > 0) 2511556Srgrimes for (off = 0; nr; nr -= nw, off += nw) 2521556Srgrimes if ((nw = write(wfd, buf + off, nr)) < 0) 2531556Srgrimes err(1, "stdout"); 25411145Sbde if (nr < 0) { 2551556Srgrimes warn("%s", filename); 25611145Sbde rval = 1; 25711145Sbde } 2581556Srgrimes} 259