cat.c revision 91079
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 91079 2002-02-22 20:51:00Z markm $"; 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 7390106Simpstatic void scanfiles(char **argv, int cooked); 7490106Simpstatic void cook_cat(FILE *); 7590106Simpstatic void raw_cat(int); 761556Srgrimes 7783482Sdillon#ifndef NO_UDOM_SUPPORT 7890106Simpstatic int udom_open(const char *path, int flags); 7983482Sdillon#endif 8083482Sdillon 811556Srgrimesint 8290106Simpmain(int argc, char *argv[]) 831556Srgrimes{ 841556Srgrimes int ch; 851556Srgrimes 8618578Sache setlocale(LC_CTYPE, ""); 8718578Sache 8824348Simp while ((ch = getopt(argc, argv, "benstuv")) != -1) 891556Srgrimes switch (ch) { 901556Srgrimes case 'b': 911556Srgrimes bflag = nflag = 1; /* -b implies -n */ 921556Srgrimes break; 931556Srgrimes case 'e': 941556Srgrimes eflag = vflag = 1; /* -e implies -v */ 951556Srgrimes break; 961556Srgrimes case 'n': 971556Srgrimes nflag = 1; 981556Srgrimes break; 991556Srgrimes case 's': 1001556Srgrimes sflag = 1; 1011556Srgrimes break; 1021556Srgrimes case 't': 1031556Srgrimes tflag = vflag = 1; /* -t implies -v */ 1041556Srgrimes break; 1051556Srgrimes case 'u': 10659239Sasmodai setbuf(stdout, NULL); 1071556Srgrimes break; 1081556Srgrimes case 'v': 1091556Srgrimes vflag = 1; 1101556Srgrimes break; 11118546Simp default: 11291079Smarkm fprintf(stderr, 1131556Srgrimes "usage: cat [-benstuv] [-] [file ...]\n"); 1141556Srgrimes exit(1); 1151556Srgrimes } 1161556Srgrimes argv += optind; 1171556Srgrimes 1181556Srgrimes if (bflag || eflag || nflag || sflag || tflag || vflag) 11983482Sdillon scanfiles(argv, 1); 1201556Srgrimes else 12183482Sdillon scanfiles(argv, 0); 1221556Srgrimes if (fclose(stdout)) 1231556Srgrimes err(1, "stdout"); 1241556Srgrimes exit(rval); 1251556Srgrimes} 1261556Srgrimes 1271556Srgrimesvoid 12890106Simpscanfiles(char **argv, int cooked) 1291556Srgrimes{ 13083482Sdillon int i = 0; 13183482Sdillon char *path; 13283961Sru FILE *fp; 1331556Srgrimes 13483482Sdillon while ((path = argv[i]) != NULL || i == 0) { 13583482Sdillon int fd; 13683482Sdillon 13783482Sdillon if (path == NULL || strcmp(path, "-") == 0) { 13883482Sdillon filename = "stdin"; 13983961Sru fd = STDIN_FILENO; 14083482Sdillon } else { 14183482Sdillon filename = path; 14283482Sdillon fd = open(path, O_RDONLY); 14383482Sdillon#ifndef NO_UDOM_SUPPORT 14483482Sdillon if (fd < 0 && errno == EOPNOTSUPP) 14583962Sru fd = udom_open(path, O_RDONLY); 14683482Sdillon#endif 1471556Srgrimes } 14883482Sdillon if (fd < 0) { 14983482Sdillon warn("%s", path); 15083482Sdillon rval = 1; 15183482Sdillon } else if (cooked) { 15283961Sru if (fd == STDIN_FILENO) 15383961Sru cook_cat(stdin); 15483961Sru else { 15583961Sru fp = fdopen(fd, "r"); 15683961Sru cook_cat(fp); 15783961Sru fclose(fp); 15883961Sru } 15983482Sdillon } else { 16083482Sdillon raw_cat(fd); 16183961Sru if (fd != STDIN_FILENO) 16283961Sru close(fd); 16383482Sdillon } 16483482Sdillon if (path == NULL) 16583482Sdillon break; 16683482Sdillon ++i; 16783482Sdillon } 1681556Srgrimes} 1691556Srgrimes 17083482Sdillonstatic void 17190106Simpcook_cat(FILE *fp) 1721556Srgrimes{ 17390106Simp int ch, gobble, line, prev; 1741556Srgrimes 17583961Sru /* Reset EOF condition on stdin. */ 17683961Sru if (fp == stdin && feof(stdin)) 17783961Sru clearerr(stdin); 17883961Sru 1791556Srgrimes line = gobble = 0; 1801556Srgrimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 1811556Srgrimes if (prev == '\n') { 1821556Srgrimes if (ch == '\n') { 1831556Srgrimes if (sflag) { 1841556Srgrimes if (!gobble && putchar(ch) == EOF) 1851556Srgrimes break; 1861556Srgrimes gobble = 1; 1871556Srgrimes continue; 1881556Srgrimes } 1891556Srgrimes if (nflag && !bflag) { 19091079Smarkm fprintf(stdout, "%6d\t", ++line); 1911556Srgrimes if (ferror(stdout)) 1921556Srgrimes break; 1931556Srgrimes } 1941556Srgrimes } else if (nflag) { 19591079Smarkm fprintf(stdout, "%6d\t", ++line); 1961556Srgrimes if (ferror(stdout)) 1971556Srgrimes break; 1981556Srgrimes } 1991556Srgrimes } 2001556Srgrimes gobble = 0; 2011556Srgrimes if (ch == '\n') { 2021556Srgrimes if (eflag) 2031556Srgrimes if (putchar('$') == EOF) 2041556Srgrimes break; 2051556Srgrimes } else if (ch == '\t') { 2061556Srgrimes if (tflag) { 2071556Srgrimes if (putchar('^') == EOF || putchar('I') == EOF) 2081556Srgrimes break; 2091556Srgrimes continue; 2101556Srgrimes } 2111556Srgrimes } else if (vflag) { 21218578Sache if (!isascii(ch) && !isprint(ch)) { 2131556Srgrimes if (putchar('M') == EOF || putchar('-') == EOF) 2141556Srgrimes break; 2151556Srgrimes ch = toascii(ch); 2161556Srgrimes } 2171556Srgrimes if (iscntrl(ch)) { 2181556Srgrimes if (putchar('^') == EOF || 2191556Srgrimes putchar(ch == '\177' ? '?' : 2201556Srgrimes ch | 0100) == EOF) 2211556Srgrimes break; 2221556Srgrimes continue; 2231556Srgrimes } 2241556Srgrimes } 2251556Srgrimes if (putchar(ch) == EOF) 2261556Srgrimes break; 2271556Srgrimes } 2281556Srgrimes if (ferror(fp)) { 2291556Srgrimes warn("%s", filename); 23011145Sbde rval = 1; 2311556Srgrimes clearerr(fp); 2321556Srgrimes } 2331556Srgrimes if (ferror(stdout)) 2341556Srgrimes err(1, "stdout"); 2351556Srgrimes} 2361556Srgrimes 23783482Sdillonstatic void 23890106Simpraw_cat(int rfd) 2391556Srgrimes{ 24090106Simp int off, wfd; 24139065Simp ssize_t nr, nw; 24239065Simp static size_t bsize; 24391079Smarkm static char *buf = NULL; 2441556Srgrimes struct stat sbuf; 2451556Srgrimes 2461556Srgrimes wfd = fileno(stdout); 2471556Srgrimes if (buf == NULL) { 2481556Srgrimes if (fstat(wfd, &sbuf)) 2491556Srgrimes err(1, "%s", filename); 2501556Srgrimes bsize = MAX(sbuf.st_blksize, 1024); 25139138Simp if ((buf = malloc(bsize)) == NULL) 25259239Sasmodai err(1, "buffer"); 2531556Srgrimes } 2541556Srgrimes while ((nr = read(rfd, buf, bsize)) > 0) 2551556Srgrimes for (off = 0; nr; nr -= nw, off += nw) 25639138Simp if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 2571556Srgrimes err(1, "stdout"); 25811145Sbde if (nr < 0) { 2591556Srgrimes warn("%s", filename); 26011145Sbde rval = 1; 26111145Sbde } 2621556Srgrimes} 26383482Sdillon 26483482Sdillon#ifndef NO_UDOM_SUPPORT 26583482Sdillon 26683482Sdillonstatic int 26790106Simpudom_open(const char *path, int flags) 26883482Sdillon{ 26983482Sdillon struct sockaddr_un sou; 27083482Sdillon int fd; 27191079Smarkm unsigned int len; 27283482Sdillon 27383482Sdillon bzero(&sou, sizeof(sou)); 27483482Sdillon 27583482Sdillon /* 27683482Sdillon * Construct the unix domain socket address and attempt to connect 27783482Sdillon */ 27891079Smarkm fd = socket(AF_UNIX, SOCK_STREAM, 0); 27991079Smarkm if (fd >= 0) { 28083482Sdillon sou.sun_family = AF_UNIX; 28183482Sdillon snprintf(sou.sun_path, sizeof(sou.sun_path), "%s", path); 28283482Sdillon len = strlen(sou.sun_path); 28383482Sdillon len = offsetof(struct sockaddr_un, sun_path[len+1]); 28483482Sdillon 28583482Sdillon if (connect(fd, (void *)&sou, len) < 0) { 28683482Sdillon close(fd); 28783482Sdillon fd = -1; 28883482Sdillon } 28983482Sdillon } 29083482Sdillon 29183482Sdillon /* 29283482Sdillon * handle the open flags by shutting down appropriate directions 29383482Sdillon */ 29483482Sdillon if (fd >= 0) { 29583482Sdillon switch(flags & O_ACCMODE) { 29683482Sdillon case O_RDONLY: 29791079Smarkm if (shutdown(fd, SHUT_WR) == -1) 29891079Smarkm perror("cat"); 29983482Sdillon break; 30083482Sdillon case O_WRONLY: 30191079Smarkm if (shutdown(fd, SHUT_RD) == -1) 30291079Smarkm perror("cat"); 30383482Sdillon break; 30483482Sdillon default: 30583482Sdillon break; 30683482Sdillon } 30783482Sdillon } 30883482Sdillon return(fd); 30983482Sdillon} 31083482Sdillon 31183482Sdillon#endif 312