cat.c revision 132433
1139743Simp/* 249267Snewton * Copyright (c) 1989, 1993 349267Snewton * The Regents of the University of California. All rights reserved. 449267Snewton * 549267Snewton * This code is derived from software contributed to Berkeley by 649267Snewton * Kevin Fall. 749267Snewton * 849267Snewton * Redistribution and use in source and binary forms, with or without 949267Snewton * modification, are permitted provided that the following conditions 1049267Snewton * are met: 1149267Snewton * 1. Redistributions of source code must retain the above copyright 1249267Snewton * notice, this list of conditions and the following disclaimer. 1349267Snewton * 2. Redistributions in binary form must reproduce the above copyright 1449267Snewton * notice, this list of conditions and the following disclaimer in the 1549267Snewton * documentation and/or other materials provided with the distribution. 1649267Snewton * 4. Neither the name of the University nor the names of its contributors 1749267Snewton * may be used to endorse or promote products derived from this software 1849267Snewton * without specific prior written permission. 1949267Snewton * 2049267Snewton * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2149267Snewton * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2249267Snewton * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2349267Snewton * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2449267Snewton * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2549267Snewton * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2649267Snewton * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2749267Snewton * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2849267Snewton * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2949267Snewton * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3049267Snewton * SUCH DAMAGE. 31116174Sobrien */ 32116174Sobrien 33116174Sobrien#if 0 3443412Snewton#ifndef lint 3543412Snewtonstatic char const copyright[] = 3643412Snewton"@(#) Copyright (c) 1989, 1993\n\ 3743412Snewton The Regents of the University of California. All rights reserved.\n"; 3843412Snewton#endif /* not lint */ 3943412Snewton#endif 4043412Snewton 4143412Snewton#ifndef lint 4248503Sgreen#if 0 4343412Snewtonstatic char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; 4443412Snewton#endif 4543412Snewton#endif /* not lint */ 4643412Snewton#include <sys/cdefs.h> 4794455Sjhb__FBSDID("$FreeBSD: head/bin/cat/cat.c 132433 2004-07-20 05:52:00Z tjr $"); 4843412Snewton 49141486Sjhb#include <sys/param.h> 5094455Sjhb#include <sys/stat.h> 5143412Snewton#ifndef NO_UDOM_SUPPORT 52141486Sjhb#include <sys/socket.h> 53141486Sjhb#include <sys/un.h> 5443412Snewton#include <errno.h> 5543412Snewton#endif 5643412Snewton 5743412Snewton#include <ctype.h> 5843412Snewton#include <err.h> 5943412Snewton#include <fcntl.h> 6043412Snewton#include <locale.h> 6165302Sobrien#include <stdio.h> 6265302Sobrien#include <stdlib.h> 6365302Sobrien#include <string.h> 6465302Sobrien#include <unistd.h> 6565302Sobrien#include <stddef.h> 6665302Sobrien 6765302Sobrienint bflag, eflag, nflag, sflag, tflag, vflag; 6865302Sobrienint rval; 6965302Sobrienconst char *filename; 7043412Snewton 7143412Snewtonstatic void usage(void); 7243412Snewtonstatic void scanfiles(char *argv[], int cooked); 7343412Snewtonstatic void cook_cat(FILE *); 7443412Snewtonstatic void raw_cat(int); 7543412Snewton 7643412Snewton#ifndef NO_UDOM_SUPPORT 7743412Snewtonstatic int udom_open(const char *path, int flags); 7843412Snewton#endif 7943412Snewton 8043412Snewtonint 8143412Snewtonmain(int argc, char *argv[]) 8243412Snewton{ 8343412Snewton int ch; 8443412Snewton 8543412Snewton setlocale(LC_CTYPE, ""); 8643412Snewton 8743412Snewton while ((ch = getopt(argc, argv, "benstuv")) != -1) 8843412Snewton switch (ch) { 8943412Snewton case 'b': 9043412Snewton bflag = nflag = 1; /* -b implies -n */ 9143412Snewton break; 9243412Snewton case 'e': 9343412Snewton eflag = vflag = 1; /* -e implies -v */ 9443412Snewton break; 9543412Snewton case 'n': 9643412Snewton nflag = 1; 9743412Snewton break; 9843412Snewton case 's': 9943412Snewton sflag = 1; 10043412Snewton break; 10143412Snewton case 't': 10243412Snewton tflag = vflag = 1; /* -t implies -v */ 10343412Snewton break; 10443412Snewton case 'u': 10543412Snewton setbuf(stdout, NULL); 10643412Snewton break; 10743412Snewton case 'v': 10843412Snewton vflag = 1; 10943412Snewton break; 11043412Snewton default: 11143412Snewton usage(); 11243412Snewton } 11343412Snewton argv += optind; 11443412Snewton 11543412Snewton if (bflag || eflag || nflag || sflag || tflag || vflag) 11643412Snewton scanfiles(argv, 1); 11743412Snewton else 11843412Snewton scanfiles(argv, 0); 11943412Snewton if (fclose(stdout)) 12043412Snewton err(1, "stdout"); 12143412Snewton exit(rval); 12243412Snewton /* NOTREACHED */ 12343412Snewton} 12443412Snewton 12543412Snewtonstatic void 12643412Snewtonusage(void) 12743412Snewton{ 12843412Snewton fprintf(stderr, "usage: cat [-benstuv] [file ...]\n"); 12943412Snewton exit(1); 13043412Snewton /* NOTREACHED */ 13143412Snewton} 13243412Snewton 13343412Snewtonstatic void 13443412Snewtonscanfiles(char *argv[], int cooked) 13543412Snewton{ 13643412Snewton int i = 0; 13743412Snewton char *path; 13843412Snewton FILE *fp; 13943412Snewton 14043412Snewton while ((path = argv[i]) != NULL || i == 0) { 14143412Snewton int fd; 14243412Snewton 14343412Snewton if (path == NULL || strcmp(path, "-") == 0) { 14443412Snewton filename = "stdin"; 14543412Snewton fd = STDIN_FILENO; 14643412Snewton } else { 14743412Snewton filename = path; 14843412Snewton fd = open(path, O_RDONLY); 14943412Snewton#ifndef NO_UDOM_SUPPORT 15043412Snewton if (fd < 0 && errno == EOPNOTSUPP) 15143412Snewton fd = udom_open(path, O_RDONLY); 15243412Snewton#endif 15343412Snewton } 15443412Snewton if (fd < 0) { 15543412Snewton warn("%s", path); 15643412Snewton rval = 1; 15743412Snewton } else if (cooked) { 15843412Snewton if (fd == STDIN_FILENO) 15959342Sobrien cook_cat(stdin); 16043412Snewton else { 16143412Snewton fp = fdopen(fd, "r"); 16243412Snewton cook_cat(fp); 16343412Snewton fclose(fp); 16443412Snewton } 16543412Snewton } else { 16643412Snewton raw_cat(fd); 16743412Snewton if (fd != STDIN_FILENO) 16843412Snewton close(fd); 16943412Snewton } 17043412Snewton if (path == NULL) 17143412Snewton break; 17251793Smarcel ++i; 17343412Snewton } 17443412Snewton} 17543412Snewton 176102808Sjakestatic void 17743412Snewtoncook_cat(FILE *fp) 17843412Snewton{ 17943412Snewton int ch, gobble, line, prev; 18043412Snewton 18149267Snewton /* Reset EOF condition on stdin. */ 18249267Snewton if (fp == stdin && feof(stdin)) 183100384Speter clearerr(stdin); 18468520Smarcel 185102808Sjake line = gobble = 0; 186102808Sjake for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 187102808Sjake if (prev == '\n') { 188102808Sjake if (sflag) { 189102808Sjake if (ch == '\n') { 190102808Sjake if (gobble) 191102808Sjake continue; 192102808Sjake gobble = 1; 193120422Speter } else 194120422Speter gobble = 0; 19543412Snewton } 19643412Snewton if (nflag && (!bflag || ch != '\n')) { 197141486Sjhb (void)fprintf(stdout, "%6d\t", ++line); 198141486Sjhb if (ferror(stdout)) 19943412Snewton break; 20099669Srobert } 201100384Speter } 20272999Sobrien if (ch == '\n') { 20359342Sobrien if (eflag && putchar('$') == EOF) 20443412Snewton break; 205123742Speter } else if (ch == '\t') { 206123742Speter if (tflag) { 20743412Snewton if (putchar('^') == EOF || putchar('I') == EOF) 20843412Snewton break; 20943412Snewton continue; 21059342Sobrien } 21143412Snewton } else if (vflag) { 212112470Sjhb if (!isascii(ch) && !isprint(ch)) { 21359342Sobrien if (putchar('M') == EOF || putchar('-') == EOF) 21443412Snewton break; 215112470Sjhb ch = toascii(ch); 216116361Sdavidxu } 217112470Sjhb if (iscntrl(ch)) { 218112470Sjhb if (putchar('^') == EOF || 219140992Ssobomax putchar(ch == '\177' ? '?' : 22043412Snewton ch | 0100) == EOF) 221112470Sjhb break; 22243412Snewton continue; 223112470Sjhb } 22443412Snewton } 22543412Snewton if (putchar(ch) == EOF) 22643412Snewton break; 22743412Snewton } 22843412Snewton if (ferror(fp)) { 22943412Snewton warn("%s", filename); 23043412Snewton rval = 1; 23143412Snewton clearerr(fp); 23277183Srwatson } 23377183Srwatson if (ferror(stdout)) 23477183Srwatson err(1, "stdout"); 23577183Srwatson} 23643412Snewton 23743412Snewtonstatic void 23843412Snewtonraw_cat(int rfd) 23943412Snewton{ 24043412Snewton int off, wfd; 24143412Snewton ssize_t nr, nw; 242140992Ssobomax static size_t bsize; 24343412Snewton static char *buf = NULL; 24443412Snewton struct stat sbuf; 24543412Snewton 24643412Snewton wfd = fileno(stdout); 24743412Snewton if (buf == NULL) { 24872091Sasmodai if (fstat(wfd, &sbuf)) 24943412Snewton err(1, "%s", filename); 25043412Snewton bsize = MAX(sbuf.st_blksize, 1024); 25143412Snewton if ((buf = malloc(bsize)) == NULL) 25243412Snewton err(1, "buffer"); 25343412Snewton } 25443412Snewton while ((nr = read(rfd, buf, bsize)) > 0) 255141486Sjhb for (off = 0; nr; nr -= nw, off += nw) 256141486Sjhb if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 25743412Snewton err(1, "stdout"); 25843412Snewton if (nr < 0) { 259141486Sjhb warn("%s", filename); 260141486Sjhb rval = 1; 26143412Snewton } 26243412Snewton} 26343412Snewton 26443412Snewton#ifndef NO_UDOM_SUPPORT 26543412Snewton 26643412Snewtonstatic int 26743412Snewtonudom_open(const char *path, int flags) 26843412Snewton{ 26943412Snewton struct sockaddr_un sou; 27043412Snewton int fd; 27143412Snewton unsigned int len; 272100384Speter 27343412Snewton bzero(&sou, sizeof(sou)); 27443412Snewton 27543412Snewton /* 27643412Snewton * Construct the unix domain socket address and attempt to connect 27743412Snewton */ 27843412Snewton fd = socket(AF_UNIX, SOCK_STREAM, 0); 27943412Snewton if (fd >= 0) { 28043597Snewton sou.sun_family = AF_UNIX; 281100384Speter if ((len = strlcpy(sou.sun_path, path, 28243597Snewton sizeof(sou.sun_path))) >= sizeof(sou.sun_path)) { 283100384Speter errno = ENAMETOOLONG; 28443412Snewton return (-1); 28543597Snewton } 28643597Snewton len = offsetof(struct sockaddr_un, sun_path[len+1]); 28743412Snewton 28843597Snewton if (connect(fd, (void *)&sou, len) < 0) { 28943597Snewton close(fd); 29043412Snewton fd = -1; 29143412Snewton } 29243412Snewton } 29343412Snewton 294132199Sphk /* 29543412Snewton * handle the open flags by shutting down appropriate directions 29643412Snewton */ 29743412Snewton if (fd >= 0) { 29843412Snewton switch(flags & O_ACCMODE) { 29943412Snewton case O_RDONLY: 30043412Snewton if (shutdown(fd, SHUT_WR) == -1) 30143412Snewton warn(NULL); 30243412Snewton break; 30343412Snewton case O_WRONLY: 30443412Snewton if (shutdown(fd, SHUT_RD) == -1) 30543412Snewton warn(NULL); 30660060Sgreen break; 307 default: 308 break; 309 } 310 } 311 return(fd); 312} 313 314#endif 315