cat.c revision 78732
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 3820412Sstevestatic char const 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 4435772Scharnier#if 0 4536000Scharnierstatic char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; 4635772Scharnier#endif 4735772Scharnierstatic const char rcsid[] = 4850471Speter "$FreeBSD: head/bin/cat/cat.c 78732 2001-06-24 23:04:23Z dd $"; 491556Srgrimes#endif /* not lint */ 501556Srgrimes 511556Srgrimes#include <sys/param.h> 521556Srgrimes#include <sys/stat.h> 531556Srgrimes 541556Srgrimes#include <ctype.h> 551556Srgrimes#include <err.h> 561556Srgrimes#include <fcntl.h> 5718578Sache#include <locale.h> 581556Srgrimes#include <stdio.h> 591556Srgrimes#include <stdlib.h> 6078732Sdd#include <string.h> 611556Srgrimes#include <unistd.h> 621556Srgrimes 631556Srgrimesint bflag, eflag, nflag, sflag, tflag, vflag; 641556Srgrimesint rval; 6539065Simpconst char *filename; 661556Srgrimes 671556Srgrimesvoid cook_args __P((char *argv[])); 681556Srgrimesvoid cook_buf __P((FILE *)); 6939138Simpint main __P((int argc, char *argv[])); 701556Srgrimesvoid raw_args __P((char *argv[])); 711556Srgrimesvoid raw_cat __P((int)); 721556Srgrimes 731556Srgrimesint 7439138Simpmain(argc, argv) 7539138Simp int argc; 7639138Simp char *argv[]; 771556Srgrimes{ 781556Srgrimes int ch; 791556Srgrimes 8018578Sache setlocale(LC_CTYPE, ""); 8118578Sache 8224348Simp while ((ch = getopt(argc, argv, "benstuv")) != -1) 831556Srgrimes switch (ch) { 841556Srgrimes case 'b': 851556Srgrimes bflag = nflag = 1; /* -b implies -n */ 861556Srgrimes break; 871556Srgrimes case 'e': 881556Srgrimes eflag = vflag = 1; /* -e implies -v */ 891556Srgrimes break; 901556Srgrimes case 'n': 911556Srgrimes nflag = 1; 921556Srgrimes break; 931556Srgrimes case 's': 941556Srgrimes sflag = 1; 951556Srgrimes break; 961556Srgrimes case 't': 971556Srgrimes tflag = vflag = 1; /* -t implies -v */ 981556Srgrimes break; 991556Srgrimes case 'u': 10059239Sasmodai setbuf(stdout, NULL); 1011556Srgrimes break; 1021556Srgrimes case 'v': 1031556Srgrimes vflag = 1; 1041556Srgrimes break; 10518546Simp default: 1061556Srgrimes (void)fprintf(stderr, 1071556Srgrimes "usage: cat [-benstuv] [-] [file ...]\n"); 1081556Srgrimes exit(1); 1091556Srgrimes } 1101556Srgrimes argv += optind; 1111556Srgrimes 1121556Srgrimes if (bflag || eflag || nflag || sflag || tflag || vflag) 1131556Srgrimes cook_args(argv); 1141556Srgrimes else 1151556Srgrimes raw_args(argv); 1161556Srgrimes if (fclose(stdout)) 1171556Srgrimes err(1, "stdout"); 1181556Srgrimes exit(rval); 1191556Srgrimes} 1201556Srgrimes 1211556Srgrimesvoid 1221556Srgrimescook_args(argv) 1231556Srgrimes char **argv; 1241556Srgrimes{ 1251556Srgrimes register FILE *fp; 1261556Srgrimes 1271556Srgrimes fp = stdin; 1281556Srgrimes filename = "stdin"; 1291556Srgrimes do { 1301556Srgrimes if (*argv) { 1311556Srgrimes if (!strcmp(*argv, "-")) 1321556Srgrimes fp = stdin; 1331556Srgrimes else if ((fp = fopen(*argv, "r")) == NULL) { 1341556Srgrimes warn("%s", *argv); 13511145Sbde rval = 1; 1361556Srgrimes ++argv; 1371556Srgrimes continue; 1381556Srgrimes } 1391556Srgrimes filename = *argv++; 1401556Srgrimes } 1411556Srgrimes cook_buf(fp); 1421556Srgrimes if (fp != stdin) 1431556Srgrimes (void)fclose(fp); 1441556Srgrimes } while (*argv); 1451556Srgrimes} 1461556Srgrimes 1471556Srgrimesvoid 1481556Srgrimescook_buf(fp) 1491556Srgrimes register FILE *fp; 1501556Srgrimes{ 1511556Srgrimes register int ch, gobble, line, prev; 1521556Srgrimes 1531556Srgrimes line = gobble = 0; 1541556Srgrimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 1551556Srgrimes if (prev == '\n') { 1561556Srgrimes if (ch == '\n') { 1571556Srgrimes if (sflag) { 1581556Srgrimes if (!gobble && putchar(ch) == EOF) 1591556Srgrimes break; 1601556Srgrimes gobble = 1; 1611556Srgrimes continue; 1621556Srgrimes } 1631556Srgrimes if (nflag && !bflag) { 1641556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1651556Srgrimes if (ferror(stdout)) 1661556Srgrimes break; 1671556Srgrimes } 1681556Srgrimes } else if (nflag) { 1691556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1701556Srgrimes if (ferror(stdout)) 1711556Srgrimes break; 1721556Srgrimes } 1731556Srgrimes } 1741556Srgrimes gobble = 0; 1751556Srgrimes if (ch == '\n') { 1761556Srgrimes if (eflag) 1771556Srgrimes if (putchar('$') == EOF) 1781556Srgrimes break; 1791556Srgrimes } else if (ch == '\t') { 1801556Srgrimes if (tflag) { 1811556Srgrimes if (putchar('^') == EOF || putchar('I') == EOF) 1821556Srgrimes break; 1831556Srgrimes continue; 1841556Srgrimes } 1851556Srgrimes } else if (vflag) { 18618578Sache if (!isascii(ch) && !isprint(ch)) { 1871556Srgrimes if (putchar('M') == EOF || putchar('-') == EOF) 1881556Srgrimes break; 1891556Srgrimes ch = toascii(ch); 1901556Srgrimes } 1911556Srgrimes if (iscntrl(ch)) { 1921556Srgrimes if (putchar('^') == EOF || 1931556Srgrimes putchar(ch == '\177' ? '?' : 1941556Srgrimes ch | 0100) == EOF) 1951556Srgrimes break; 1961556Srgrimes continue; 1971556Srgrimes } 1981556Srgrimes } 1991556Srgrimes if (putchar(ch) == EOF) 2001556Srgrimes break; 2011556Srgrimes } 2021556Srgrimes if (ferror(fp)) { 2031556Srgrimes warn("%s", filename); 20411145Sbde rval = 1; 2051556Srgrimes clearerr(fp); 2061556Srgrimes } 2071556Srgrimes if (ferror(stdout)) 2081556Srgrimes err(1, "stdout"); 2091556Srgrimes} 2101556Srgrimes 2111556Srgrimesvoid 2121556Srgrimesraw_args(argv) 2131556Srgrimes char **argv; 2141556Srgrimes{ 2151556Srgrimes register int fd; 2161556Srgrimes 2171556Srgrimes fd = fileno(stdin); 2181556Srgrimes filename = "stdin"; 2191556Srgrimes do { 2201556Srgrimes if (*argv) { 2211556Srgrimes if (!strcmp(*argv, "-")) 2221556Srgrimes fd = fileno(stdin); 2231556Srgrimes else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { 2241556Srgrimes warn("%s", *argv); 22511145Sbde rval = 1; 2261556Srgrimes ++argv; 2271556Srgrimes continue; 2281556Srgrimes } 2291556Srgrimes filename = *argv++; 2301556Srgrimes } 2311556Srgrimes raw_cat(fd); 2321556Srgrimes if (fd != fileno(stdin)) 2331556Srgrimes (void)close(fd); 2341556Srgrimes } while (*argv); 2351556Srgrimes} 2361556Srgrimes 2371556Srgrimesvoid 2381556Srgrimesraw_cat(rfd) 2391556Srgrimes register int rfd; 2401556Srgrimes{ 24139065Simp register int off, wfd; 24239065Simp ssize_t nr, nw; 24339065Simp static size_t bsize; 2441556Srgrimes static char *buf; 2451556Srgrimes struct stat sbuf; 2461556Srgrimes 2471556Srgrimes wfd = fileno(stdout); 2481556Srgrimes if (buf == NULL) { 2491556Srgrimes if (fstat(wfd, &sbuf)) 2501556Srgrimes err(1, "%s", filename); 2511556Srgrimes bsize = MAX(sbuf.st_blksize, 1024); 25239138Simp if ((buf = malloc(bsize)) == NULL) 25359239Sasmodai err(1, "buffer"); 2541556Srgrimes } 2551556Srgrimes while ((nr = read(rfd, buf, bsize)) > 0) 2561556Srgrimes for (off = 0; nr; nr -= nw, off += nw) 25739138Simp if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 2581556Srgrimes err(1, "stdout"); 25911145Sbde if (nr < 0) { 2601556Srgrimes warn("%s", filename); 26111145Sbde rval = 1; 26211145Sbde } 2631556Srgrimes} 264