cat.c revision 83962
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 83962 2001-09-26 11:34:14Z ru $"; 491556Srgrimes#endif /* not lint */ 501556Srgrimes 511556Srgrimes#include <sys/param.h> 521556Srgrimes#include <sys/stat.h> 5383482Sdillon#ifndef NO_UDOM_SUPPORT 5483482Sdillon#include <sys/socket.h> 5583482Sdillon#include <sys/un.h> 5683482Sdillon#include <errno.h> 5783482Sdillon#endif 581556Srgrimes 591556Srgrimes#include <ctype.h> 601556Srgrimes#include <err.h> 611556Srgrimes#include <fcntl.h> 6218578Sache#include <locale.h> 631556Srgrimes#include <stdio.h> 641556Srgrimes#include <stdlib.h> 6578732Sdd#include <string.h> 661556Srgrimes#include <unistd.h> 6783482Sdillon#include <stddef.h> 681556Srgrimes 691556Srgrimesint bflag, eflag, nflag, sflag, tflag, vflag; 701556Srgrimesint rval; 7139065Simpconst char *filename; 721556Srgrimes 7339138Simpint main __P((int argc, char *argv[])); 741556Srgrimes 7583482Sdillonstatic void scanfiles __P((char **argv, int cooked)); 7683482Sdillonstatic void cook_cat __P((FILE *)); 7783482Sdillonstatic void raw_cat __P((int)); 7883482Sdillon 7983482Sdillon#ifndef NO_UDOM_SUPPORT 8083962Srustatic int udom_open __P((const char *path, int flags)); 8183482Sdillon#endif 8283482Sdillon 831556Srgrimesint 8439138Simpmain(argc, argv) 8539138Simp int argc; 8639138Simp char *argv[]; 871556Srgrimes{ 881556Srgrimes int ch; 891556Srgrimes 9018578Sache setlocale(LC_CTYPE, ""); 9118578Sache 9224348Simp while ((ch = getopt(argc, argv, "benstuv")) != -1) 931556Srgrimes switch (ch) { 941556Srgrimes case 'b': 951556Srgrimes bflag = nflag = 1; /* -b implies -n */ 961556Srgrimes break; 971556Srgrimes case 'e': 981556Srgrimes eflag = vflag = 1; /* -e implies -v */ 991556Srgrimes break; 1001556Srgrimes case 'n': 1011556Srgrimes nflag = 1; 1021556Srgrimes break; 1031556Srgrimes case 's': 1041556Srgrimes sflag = 1; 1051556Srgrimes break; 1061556Srgrimes case 't': 1071556Srgrimes tflag = vflag = 1; /* -t implies -v */ 1081556Srgrimes break; 1091556Srgrimes case 'u': 11059239Sasmodai setbuf(stdout, NULL); 1111556Srgrimes break; 1121556Srgrimes case 'v': 1131556Srgrimes vflag = 1; 1141556Srgrimes break; 11518546Simp default: 1161556Srgrimes (void)fprintf(stderr, 1171556Srgrimes "usage: cat [-benstuv] [-] [file ...]\n"); 1181556Srgrimes exit(1); 1191556Srgrimes } 1201556Srgrimes argv += optind; 1211556Srgrimes 1221556Srgrimes if (bflag || eflag || nflag || sflag || tflag || vflag) 12383482Sdillon scanfiles(argv, 1); 1241556Srgrimes else 12583482Sdillon scanfiles(argv, 0); 1261556Srgrimes if (fclose(stdout)) 1271556Srgrimes err(1, "stdout"); 1281556Srgrimes exit(rval); 1291556Srgrimes} 1301556Srgrimes 1311556Srgrimesvoid 13283482Sdillonscanfiles(argv, cooked) 13383482Sdillon char **argv; 13483482Sdillon int cooked; 1351556Srgrimes{ 13683482Sdillon int i = 0; 13783482Sdillon char *path; 13883961Sru FILE *fp; 1391556Srgrimes 14083482Sdillon while ((path = argv[i]) != NULL || i == 0) { 14183482Sdillon int fd; 14283482Sdillon 14383482Sdillon if (path == NULL || strcmp(path, "-") == 0) { 14483482Sdillon filename = "stdin"; 14583961Sru fd = STDIN_FILENO; 14683482Sdillon } else { 14783482Sdillon filename = path; 14883482Sdillon fd = open(path, O_RDONLY); 14983482Sdillon#ifndef NO_UDOM_SUPPORT 15083482Sdillon if (fd < 0 && errno == EOPNOTSUPP) 15183962Sru fd = udom_open(path, O_RDONLY); 15283482Sdillon#endif 1531556Srgrimes } 15483482Sdillon if (fd < 0) { 15583482Sdillon warn("%s", path); 15683482Sdillon rval = 1; 15783482Sdillon } else if (cooked) { 15883961Sru if (fd == STDIN_FILENO) 15983961Sru cook_cat(stdin); 16083961Sru else { 16183961Sru fp = fdopen(fd, "r"); 16283961Sru cook_cat(fp); 16383961Sru fclose(fp); 16483961Sru } 16583482Sdillon } else { 16683482Sdillon raw_cat(fd); 16783961Sru if (fd != STDIN_FILENO) 16883961Sru close(fd); 16983482Sdillon } 17083482Sdillon if (path == NULL) 17183482Sdillon break; 17283482Sdillon ++i; 17383482Sdillon } 1741556Srgrimes} 1751556Srgrimes 17683482Sdillonstatic void 17783482Sdilloncook_cat(fp) 1781556Srgrimes register FILE *fp; 1791556Srgrimes{ 1801556Srgrimes register int ch, gobble, line, prev; 1811556Srgrimes 18283961Sru /* Reset EOF condition on stdin. */ 18383961Sru if (fp == stdin && feof(stdin)) 18483961Sru clearerr(stdin); 18583961Sru 1861556Srgrimes line = gobble = 0; 1871556Srgrimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 1881556Srgrimes if (prev == '\n') { 1891556Srgrimes if (ch == '\n') { 1901556Srgrimes if (sflag) { 1911556Srgrimes if (!gobble && putchar(ch) == EOF) 1921556Srgrimes break; 1931556Srgrimes gobble = 1; 1941556Srgrimes continue; 1951556Srgrimes } 1961556Srgrimes if (nflag && !bflag) { 1971556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 1981556Srgrimes if (ferror(stdout)) 1991556Srgrimes break; 2001556Srgrimes } 2011556Srgrimes } else if (nflag) { 2021556Srgrimes (void)fprintf(stdout, "%6d\t", ++line); 2031556Srgrimes if (ferror(stdout)) 2041556Srgrimes break; 2051556Srgrimes } 2061556Srgrimes } 2071556Srgrimes gobble = 0; 2081556Srgrimes if (ch == '\n') { 2091556Srgrimes if (eflag) 2101556Srgrimes if (putchar('$') == EOF) 2111556Srgrimes break; 2121556Srgrimes } else if (ch == '\t') { 2131556Srgrimes if (tflag) { 2141556Srgrimes if (putchar('^') == EOF || putchar('I') == EOF) 2151556Srgrimes break; 2161556Srgrimes continue; 2171556Srgrimes } 2181556Srgrimes } else if (vflag) { 21918578Sache if (!isascii(ch) && !isprint(ch)) { 2201556Srgrimes if (putchar('M') == EOF || putchar('-') == EOF) 2211556Srgrimes break; 2221556Srgrimes ch = toascii(ch); 2231556Srgrimes } 2241556Srgrimes if (iscntrl(ch)) { 2251556Srgrimes if (putchar('^') == EOF || 2261556Srgrimes putchar(ch == '\177' ? '?' : 2271556Srgrimes ch | 0100) == EOF) 2281556Srgrimes break; 2291556Srgrimes continue; 2301556Srgrimes } 2311556Srgrimes } 2321556Srgrimes if (putchar(ch) == EOF) 2331556Srgrimes break; 2341556Srgrimes } 2351556Srgrimes if (ferror(fp)) { 2361556Srgrimes warn("%s", filename); 23711145Sbde rval = 1; 2381556Srgrimes clearerr(fp); 2391556Srgrimes } 2401556Srgrimes if (ferror(stdout)) 2411556Srgrimes err(1, "stdout"); 2421556Srgrimes} 2431556Srgrimes 24483482Sdillonstatic void 2451556Srgrimesraw_cat(rfd) 2461556Srgrimes register int rfd; 2471556Srgrimes{ 24839065Simp register int off, wfd; 24939065Simp ssize_t nr, nw; 25039065Simp static size_t bsize; 2511556Srgrimes static char *buf; 2521556Srgrimes struct stat sbuf; 2531556Srgrimes 2541556Srgrimes wfd = fileno(stdout); 2551556Srgrimes if (buf == NULL) { 2561556Srgrimes if (fstat(wfd, &sbuf)) 2571556Srgrimes err(1, "%s", filename); 2581556Srgrimes bsize = MAX(sbuf.st_blksize, 1024); 25939138Simp if ((buf = malloc(bsize)) == NULL) 26059239Sasmodai err(1, "buffer"); 2611556Srgrimes } 2621556Srgrimes while ((nr = read(rfd, buf, bsize)) > 0) 2631556Srgrimes for (off = 0; nr; nr -= nw, off += nw) 26439138Simp if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 2651556Srgrimes err(1, "stdout"); 26611145Sbde if (nr < 0) { 2671556Srgrimes warn("%s", filename); 26811145Sbde rval = 1; 26911145Sbde } 2701556Srgrimes} 27183482Sdillon 27283482Sdillon#ifndef NO_UDOM_SUPPORT 27383482Sdillon 27483482Sdillonstatic int 27583962Sruudom_open(path, flags) 27683482Sdillon const char *path; 27783482Sdillon int flags; 27883482Sdillon{ 27983482Sdillon struct sockaddr_un sou; 28083482Sdillon int fd; 28183482Sdillon int len; 28283482Sdillon 28383482Sdillon bzero(&sou, sizeof(sou)); 28483482Sdillon 28583482Sdillon /* 28683482Sdillon * Construct the unix domain socket address and attempt to connect 28783482Sdillon */ 28883482Sdillon if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) { 28983482Sdillon sou.sun_family = AF_UNIX; 29083482Sdillon snprintf(sou.sun_path, sizeof(sou.sun_path), "%s", path); 29183482Sdillon len = strlen(sou.sun_path); 29283482Sdillon len = offsetof(struct sockaddr_un, sun_path[len+1]); 29383482Sdillon 29483482Sdillon if (connect(fd, (void *)&sou, len) < 0) { 29583482Sdillon close(fd); 29683482Sdillon fd = -1; 29783482Sdillon } 29883482Sdillon } 29983482Sdillon 30083482Sdillon /* 30183482Sdillon * handle the open flags by shutting down appropriate directions 30283482Sdillon */ 30383482Sdillon if (fd >= 0) { 30483482Sdillon switch(flags & O_ACCMODE) { 30583482Sdillon case O_RDONLY: 30683482Sdillon shutdown(fd, SHUT_WR); 30783482Sdillon break; 30883482Sdillon case O_WRONLY: 30983482Sdillon shutdown(fd, SHUT_RD); 31083482Sdillon break; 31183482Sdillon default: 31283482Sdillon break; 31383482Sdillon } 31483482Sdillon } 31583482Sdillon return(fd); 31683482Sdillon} 31783482Sdillon 31883482Sdillon#endif 31983482Sdillon 320