cat.c revision 101092
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 471556Srgrimes#endif /* not lint */ 4899109Sobrien#include <sys/cdefs.h> 4999109Sobrien__FBSDID("$FreeBSD: head/bin/cat/cat.c 101092 2002-07-31 16:50:21Z markm $"); 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 7398216Sjmallettstatic void usage(void); 7490106Simpstatic void scanfiles(char **argv, int cooked); 7590106Simpstatic void cook_cat(FILE *); 7690106Simpstatic void raw_cat(int); 771556Srgrimes 7883482Sdillon#ifndef NO_UDOM_SUPPORT 7990106Simpstatic int udom_open(const char *path, int flags); 8083482Sdillon#endif 8183482Sdillon 821556Srgrimesint 8390106Simpmain(int argc, char *argv[]) 841556Srgrimes{ 851556Srgrimes int ch; 861556Srgrimes 8718578Sache setlocale(LC_CTYPE, ""); 8818578Sache 8924348Simp while ((ch = getopt(argc, argv, "benstuv")) != -1) 901556Srgrimes switch (ch) { 911556Srgrimes case 'b': 921556Srgrimes bflag = nflag = 1; /* -b implies -n */ 931556Srgrimes break; 941556Srgrimes case 'e': 951556Srgrimes eflag = vflag = 1; /* -e implies -v */ 961556Srgrimes break; 971556Srgrimes case 'n': 981556Srgrimes nflag = 1; 991556Srgrimes break; 1001556Srgrimes case 's': 1011556Srgrimes sflag = 1; 1021556Srgrimes break; 1031556Srgrimes case 't': 1041556Srgrimes tflag = vflag = 1; /* -t implies -v */ 1051556Srgrimes break; 1061556Srgrimes case 'u': 10759239Sasmodai setbuf(stdout, NULL); 1081556Srgrimes break; 1091556Srgrimes case 'v': 1101556Srgrimes vflag = 1; 1111556Srgrimes break; 11218546Simp default: 11398216Sjmallett usage(); 1141556Srgrimes } 1151556Srgrimes argv += optind; 1161556Srgrimes 1171556Srgrimes if (bflag || eflag || nflag || sflag || tflag || vflag) 11883482Sdillon scanfiles(argv, 1); 1191556Srgrimes else 12083482Sdillon scanfiles(argv, 0); 1211556Srgrimes if (fclose(stdout)) 1221556Srgrimes err(1, "stdout"); 1231556Srgrimes exit(rval); 124101092Smarkm /* NOTREACHED */ 1251556Srgrimes} 1261556Srgrimes 12798216Sjmallettstatic void 12898216Sjmallettusage(void) 12998216Sjmallett{ 13098216Sjmallett fprintf(stderr, "usage: cat [-benstuv] [file ...]\n"); 13198216Sjmallett exit(1); 132101092Smarkm /* NOTREACHED */ 13398216Sjmallett} 13498216Sjmallett 1351556Srgrimesvoid 13690106Simpscanfiles(char **argv, int cooked) 1371556Srgrimes{ 13883482Sdillon int i = 0; 13983482Sdillon char *path; 14083961Sru FILE *fp; 1411556Srgrimes 14283482Sdillon while ((path = argv[i]) != NULL || i == 0) { 14383482Sdillon int fd; 14483482Sdillon 14583482Sdillon if (path == NULL || strcmp(path, "-") == 0) { 14683482Sdillon filename = "stdin"; 14783961Sru fd = STDIN_FILENO; 14883482Sdillon } else { 14983482Sdillon filename = path; 15083482Sdillon fd = open(path, O_RDONLY); 15183482Sdillon#ifndef NO_UDOM_SUPPORT 15283482Sdillon if (fd < 0 && errno == EOPNOTSUPP) 15383962Sru fd = udom_open(path, O_RDONLY); 15483482Sdillon#endif 1551556Srgrimes } 15683482Sdillon if (fd < 0) { 15783482Sdillon warn("%s", path); 15883482Sdillon rval = 1; 15983482Sdillon } else if (cooked) { 16083961Sru if (fd == STDIN_FILENO) 16183961Sru cook_cat(stdin); 16283961Sru else { 16383961Sru fp = fdopen(fd, "r"); 16483961Sru cook_cat(fp); 16583961Sru fclose(fp); 16683961Sru } 16783482Sdillon } else { 16883482Sdillon raw_cat(fd); 16983961Sru if (fd != STDIN_FILENO) 17083961Sru close(fd); 17183482Sdillon } 17283482Sdillon if (path == NULL) 17383482Sdillon break; 17483482Sdillon ++i; 17583482Sdillon } 1761556Srgrimes} 1771556Srgrimes 17883482Sdillonstatic void 17990106Simpcook_cat(FILE *fp) 1801556Srgrimes{ 18190106Simp int ch, gobble, line, prev; 1821556Srgrimes 18383961Sru /* Reset EOF condition on stdin. */ 18483961Sru if (fp == stdin && feof(stdin)) 18583961Sru clearerr(stdin); 18683961Sru 1871556Srgrimes line = gobble = 0; 1881556Srgrimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 1891556Srgrimes if (prev == '\n') { 19098169Stjr if (sflag) { 19198169Stjr if (ch == '\n') { 19298169Stjr if (gobble) 19398169Stjr continue; 1941556Srgrimes gobble = 1; 19598169Stjr } else 19698169Stjr gobble = 0; 19798169Stjr } 19898169Stjr if (nflag && (!bflag || ch != '\n')) { 19998169Stjr (void)fprintf(stdout, "%6d\t", ++line); 2001556Srgrimes if (ferror(stdout)) 2011556Srgrimes break; 2021556Srgrimes } 2031556Srgrimes } 2041556Srgrimes if (ch == '\n') { 20598169Stjr if (eflag && putchar('$') == EOF) 20698169Stjr break; 2071556Srgrimes } else if (ch == '\t') { 2081556Srgrimes if (tflag) { 2091556Srgrimes if (putchar('^') == EOF || putchar('I') == EOF) 2101556Srgrimes break; 2111556Srgrimes continue; 2121556Srgrimes } 2131556Srgrimes } else if (vflag) { 21418578Sache if (!isascii(ch) && !isprint(ch)) { 2151556Srgrimes if (putchar('M') == EOF || putchar('-') == EOF) 2161556Srgrimes break; 2171556Srgrimes ch = toascii(ch); 2181556Srgrimes } 2191556Srgrimes if (iscntrl(ch)) { 2201556Srgrimes if (putchar('^') == EOF || 2211556Srgrimes putchar(ch == '\177' ? '?' : 2221556Srgrimes ch | 0100) == EOF) 2231556Srgrimes break; 2241556Srgrimes continue; 2251556Srgrimes } 2261556Srgrimes } 2271556Srgrimes if (putchar(ch) == EOF) 2281556Srgrimes break; 2291556Srgrimes } 2301556Srgrimes if (ferror(fp)) { 2311556Srgrimes warn("%s", filename); 23211145Sbde rval = 1; 2331556Srgrimes clearerr(fp); 2341556Srgrimes } 2351556Srgrimes if (ferror(stdout)) 2361556Srgrimes err(1, "stdout"); 2371556Srgrimes} 2381556Srgrimes 23983482Sdillonstatic void 24090106Simpraw_cat(int rfd) 2411556Srgrimes{ 24290106Simp int off, wfd; 24339065Simp ssize_t nr, nw; 24439065Simp static size_t bsize; 24591079Smarkm static char *buf = NULL; 2461556Srgrimes struct stat sbuf; 2471556Srgrimes 2481556Srgrimes wfd = fileno(stdout); 2491556Srgrimes if (buf == NULL) { 2501556Srgrimes if (fstat(wfd, &sbuf)) 2511556Srgrimes err(1, "%s", filename); 2521556Srgrimes bsize = MAX(sbuf.st_blksize, 1024); 25339138Simp if ((buf = malloc(bsize)) == NULL) 25459239Sasmodai err(1, "buffer"); 2551556Srgrimes } 2561556Srgrimes while ((nr = read(rfd, buf, bsize)) > 0) 2571556Srgrimes for (off = 0; nr; nr -= nw, off += nw) 25839138Simp if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 2591556Srgrimes err(1, "stdout"); 26011145Sbde if (nr < 0) { 2611556Srgrimes warn("%s", filename); 26211145Sbde rval = 1; 26311145Sbde } 2641556Srgrimes} 26583482Sdillon 26683482Sdillon#ifndef NO_UDOM_SUPPORT 26783482Sdillon 26883482Sdillonstatic int 26990106Simpudom_open(const char *path, int flags) 27083482Sdillon{ 27183482Sdillon struct sockaddr_un sou; 27283482Sdillon int fd; 27391079Smarkm unsigned int len; 27483482Sdillon 27583482Sdillon bzero(&sou, sizeof(sou)); 27683482Sdillon 27783482Sdillon /* 27883482Sdillon * Construct the unix domain socket address and attempt to connect 27983482Sdillon */ 28091079Smarkm fd = socket(AF_UNIX, SOCK_STREAM, 0); 28191079Smarkm if (fd >= 0) { 28283482Sdillon sou.sun_family = AF_UNIX; 28399022Stjr if ((len = strlcpy(sou.sun_path, path, 28499022Stjr sizeof(sou.sun_path))) >= sizeof(sou.sun_path)) { 28599022Stjr errno = ENAMETOOLONG; 28699022Stjr return (-1); 28799022Stjr } 28883482Sdillon len = offsetof(struct sockaddr_un, sun_path[len+1]); 28983482Sdillon 29083482Sdillon if (connect(fd, (void *)&sou, len) < 0) { 29183482Sdillon close(fd); 29283482Sdillon fd = -1; 29383482Sdillon } 29483482Sdillon } 29583482Sdillon 29683482Sdillon /* 29783482Sdillon * handle the open flags by shutting down appropriate directions 29883482Sdillon */ 29983482Sdillon if (fd >= 0) { 30083482Sdillon switch(flags & O_ACCMODE) { 30183482Sdillon case O_RDONLY: 30291079Smarkm if (shutdown(fd, SHUT_WR) == -1) 30391079Smarkm perror("cat"); 30483482Sdillon break; 30583482Sdillon case O_WRONLY: 30691079Smarkm if (shutdown(fd, SHUT_RD) == -1) 30791079Smarkm perror("cat"); 30883482Sdillon break; 30983482Sdillon default: 31083482Sdillon break; 31183482Sdillon } 31283482Sdillon } 31383482Sdillon return(fd); 31483482Sdillon} 31583482Sdillon 31683482Sdillon#endif 317