14b88c807SRodney W. Grimes /* 24b88c807SRodney W. Grimes * Copyright (c) 1989, 1993 34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 44b88c807SRodney W. Grimes * 54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 64b88c807SRodney W. Grimes * Kevin Fall. 74b88c807SRodney W. Grimes * 84b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 94b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 104b88c807SRodney W. Grimes * are met: 114b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 124b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 134b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 154b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 164b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 174b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 184b88c807SRodney W. Grimes * without specific prior written permission. 194b88c807SRodney W. Grimes * 204b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 214b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 244b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304b88c807SRodney W. Grimes * SUCH DAMAGE. 314b88c807SRodney W. Grimes */ 324b88c807SRodney W. Grimes 330d22cdf0SDavid E. O'Brien #if 0 344b88c807SRodney W. Grimes #ifndef lint 35890acb95SSteve Price static char const copyright[] = 364b88c807SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 374b88c807SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 384b88c807SRodney W. Grimes #endif /* not lint */ 390d22cdf0SDavid E. O'Brien #endif 404b88c807SRodney W. Grimes 414b88c807SRodney W. Grimes #ifndef lint 424c95995fSPhilippe Charnier #if 0 4312f93eb9SPhilippe Charnier static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; 444c95995fSPhilippe Charnier #endif 454b88c807SRodney W. Grimes #endif /* not lint */ 465eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 475eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 484b88c807SRodney W. Grimes 494b88c807SRodney W. Grimes #include <sys/param.h> 504b88c807SRodney W. Grimes #include <sys/stat.h> 51cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 52cbf2d71fSMatthew Dillon #include <sys/socket.h> 53cbf2d71fSMatthew Dillon #include <sys/un.h> 54cbf2d71fSMatthew Dillon #include <errno.h> 55cbf2d71fSMatthew Dillon #endif 564b88c807SRodney W. Grimes 574b88c807SRodney W. Grimes #include <ctype.h> 584b88c807SRodney W. Grimes #include <err.h> 594b88c807SRodney W. Grimes #include <fcntl.h> 603043192bSAndrey A. Chernov #include <locale.h> 614b88c807SRodney W. Grimes #include <stdio.h> 624b88c807SRodney W. Grimes #include <stdlib.h> 63cafefe8cSDima Dorfman #include <string.h> 644b88c807SRodney W. Grimes #include <unistd.h> 65cbf2d71fSMatthew Dillon #include <stddef.h> 664b88c807SRodney W. Grimes 674b88c807SRodney W. Grimes int bflag, eflag, nflag, sflag, tflag, vflag; 684b88c807SRodney W. Grimes int rval; 69a5da0999SWarner Losh const char *filename; 704b88c807SRodney W. Grimes 71ca2be2ffSJuli Mallett static void usage(void); 729d32ecfcSMark Murray static void scanfiles(char *argv[], int cooked); 7378a3801dSWarner Losh static void cook_cat(FILE *); 7478a3801dSWarner Losh static void raw_cat(int); 75cbf2d71fSMatthew Dillon 76cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 7778a3801dSWarner Losh static int udom_open(const char *path, int flags); 78cbf2d71fSMatthew Dillon #endif 794b88c807SRodney W. Grimes 804b88c807SRodney W. Grimes int 8178a3801dSWarner Losh main(int argc, char *argv[]) 824b88c807SRodney W. Grimes { 834b88c807SRodney W. Grimes int ch; 844b88c807SRodney W. Grimes 853043192bSAndrey A. Chernov setlocale(LC_CTYPE, ""); 863043192bSAndrey A. Chernov 8793ef08afSWarner Losh while ((ch = getopt(argc, argv, "benstuv")) != -1) 884b88c807SRodney W. Grimes switch (ch) { 894b88c807SRodney W. Grimes case 'b': 904b88c807SRodney W. Grimes bflag = nflag = 1; /* -b implies -n */ 914b88c807SRodney W. Grimes break; 924b88c807SRodney W. Grimes case 'e': 934b88c807SRodney W. Grimes eflag = vflag = 1; /* -e implies -v */ 944b88c807SRodney W. Grimes break; 954b88c807SRodney W. Grimes case 'n': 964b88c807SRodney W. Grimes nflag = 1; 974b88c807SRodney W. Grimes break; 984b88c807SRodney W. Grimes case 's': 994b88c807SRodney W. Grimes sflag = 1; 1004b88c807SRodney W. Grimes break; 1014b88c807SRodney W. Grimes case 't': 1024b88c807SRodney W. Grimes tflag = vflag = 1; /* -t implies -v */ 1034b88c807SRodney W. Grimes break; 1044b88c807SRodney W. Grimes case 'u': 1052192b407SJeroen Ruigrok van der Werven setbuf(stdout, NULL); 1064b88c807SRodney W. Grimes break; 1074b88c807SRodney W. Grimes case 'v': 1084b88c807SRodney W. Grimes vflag = 1; 1094b88c807SRodney W. Grimes break; 1108d72a3d7SWarner Losh default: 111ca2be2ffSJuli Mallett usage(); 1124b88c807SRodney W. Grimes } 1134b88c807SRodney W. Grimes argv += optind; 1144b88c807SRodney W. Grimes 1154b88c807SRodney W. Grimes if (bflag || eflag || nflag || sflag || tflag || vflag) 116cbf2d71fSMatthew Dillon scanfiles(argv, 1); 1174b88c807SRodney W. Grimes else 118cbf2d71fSMatthew Dillon scanfiles(argv, 0); 1194b88c807SRodney W. Grimes if (fclose(stdout)) 1204b88c807SRodney W. Grimes err(1, "stdout"); 1214b88c807SRodney W. Grimes exit(rval); 1229f82c1d3SMark Murray /* NOTREACHED */ 1234b88c807SRodney W. Grimes } 1244b88c807SRodney W. Grimes 125ca2be2ffSJuli Mallett static void 126ca2be2ffSJuli Mallett usage(void) 127ca2be2ffSJuli Mallett { 128ca2be2ffSJuli Mallett fprintf(stderr, "usage: cat [-benstuv] [file ...]\n"); 129ca2be2ffSJuli Mallett exit(1); 1309f82c1d3SMark Murray /* NOTREACHED */ 131ca2be2ffSJuli Mallett } 132ca2be2ffSJuli Mallett 1339d32ecfcSMark Murray static void 1349d32ecfcSMark Murray scanfiles(char *argv[], int cooked) 1354b88c807SRodney W. Grimes { 136cbf2d71fSMatthew Dillon int i = 0; 137cbf2d71fSMatthew Dillon char *path; 1381b00c916SRuslan Ermilov FILE *fp; 1394b88c807SRodney W. Grimes 140cbf2d71fSMatthew Dillon while ((path = argv[i]) != NULL || i == 0) { 141cbf2d71fSMatthew Dillon int fd; 142cbf2d71fSMatthew Dillon 143cbf2d71fSMatthew Dillon if (path == NULL || strcmp(path, "-") == 0) { 1444b88c807SRodney W. Grimes filename = "stdin"; 1451b00c916SRuslan Ermilov fd = STDIN_FILENO; 146cbf2d71fSMatthew Dillon } else { 147cbf2d71fSMatthew Dillon filename = path; 148cbf2d71fSMatthew Dillon fd = open(path, O_RDONLY); 149cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 150cbf2d71fSMatthew Dillon if (fd < 0 && errno == EOPNOTSUPP) 15143e09ab2SRuslan Ermilov fd = udom_open(path, O_RDONLY); 152cbf2d71fSMatthew Dillon #endif 153cbf2d71fSMatthew Dillon } 154cbf2d71fSMatthew Dillon if (fd < 0) { 155cbf2d71fSMatthew Dillon warn("%s", path); 156001aff9fSBruce Evans rval = 1; 157cbf2d71fSMatthew Dillon } else if (cooked) { 1581b00c916SRuslan Ermilov if (fd == STDIN_FILENO) 1591b00c916SRuslan Ermilov cook_cat(stdin); 1601b00c916SRuslan Ermilov else { 1611b00c916SRuslan Ermilov fp = fdopen(fd, "r"); 162cbf2d71fSMatthew Dillon cook_cat(fp); 163cbf2d71fSMatthew Dillon fclose(fp); 1641b00c916SRuslan Ermilov } 165cbf2d71fSMatthew Dillon } else { 166cbf2d71fSMatthew Dillon raw_cat(fd); 1671b00c916SRuslan Ermilov if (fd != STDIN_FILENO) 168cbf2d71fSMatthew Dillon close(fd); 1694b88c807SRodney W. Grimes } 170cbf2d71fSMatthew Dillon if (path == NULL) 171cbf2d71fSMatthew Dillon break; 172cbf2d71fSMatthew Dillon ++i; 1734b88c807SRodney W. Grimes } 1744b88c807SRodney W. Grimes } 1754b88c807SRodney W. Grimes 176cbf2d71fSMatthew Dillon static void 17778a3801dSWarner Losh cook_cat(FILE *fp) 1784b88c807SRodney W. Grimes { 17978a3801dSWarner Losh int ch, gobble, line, prev; 1804b88c807SRodney W. Grimes 1811b00c916SRuslan Ermilov /* Reset EOF condition on stdin. */ 1821b00c916SRuslan Ermilov if (fp == stdin && feof(stdin)) 1831b00c916SRuslan Ermilov clearerr(stdin); 1841b00c916SRuslan Ermilov 1854b88c807SRodney W. Grimes line = gobble = 0; 1864b88c807SRodney W. Grimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 1874b88c807SRodney W. Grimes if (prev == '\n') { 1884b88c807SRodney W. Grimes if (sflag) { 1894b88c807SRodney W. Grimes if (ch == '\n') { 190bf5f0c44STim J. Robbins if (gobble) 191bf5f0c44STim J. Robbins continue; 192bf5f0c44STim J. Robbins gobble = 1; 193bf5f0c44STim J. Robbins } else 194bf5f0c44STim J. Robbins gobble = 0; 195bf5f0c44STim J. Robbins } 196bf5f0c44STim J. Robbins if (nflag && (!bflag || ch != '\n')) { 197bf5f0c44STim J. Robbins (void)fprintf(stdout, "%6d\t", ++line); 198bf5f0c44STim J. Robbins if (ferror(stdout)) 199bf5f0c44STim J. Robbins break; 200bf5f0c44STim J. Robbins } 201bf5f0c44STim J. Robbins } 202bf5f0c44STim J. Robbins if (ch == '\n') { 203bf5f0c44STim J. Robbins if (eflag && putchar('$') == EOF) 2044b88c807SRodney W. Grimes break; 2054b88c807SRodney W. Grimes } else if (ch == '\t') { 2064b88c807SRodney W. Grimes if (tflag) { 2074b88c807SRodney W. Grimes if (putchar('^') == EOF || putchar('I') == EOF) 2084b88c807SRodney W. Grimes break; 2094b88c807SRodney W. Grimes continue; 2104b88c807SRodney W. Grimes } 2114b88c807SRodney W. Grimes } else if (vflag) { 2123043192bSAndrey A. Chernov if (!isascii(ch) && !isprint(ch)) { 2134b88c807SRodney W. Grimes if (putchar('M') == EOF || putchar('-') == EOF) 2144b88c807SRodney W. Grimes break; 2154b88c807SRodney W. Grimes ch = toascii(ch); 2164b88c807SRodney W. Grimes } 2174b88c807SRodney W. Grimes if (iscntrl(ch)) { 2184b88c807SRodney W. Grimes if (putchar('^') == EOF || 2194b88c807SRodney W. Grimes putchar(ch == '\177' ? '?' : 2204b88c807SRodney W. Grimes ch | 0100) == EOF) 2214b88c807SRodney W. Grimes break; 2224b88c807SRodney W. Grimes continue; 2234b88c807SRodney W. Grimes } 2244b88c807SRodney W. Grimes } 2254b88c807SRodney W. Grimes if (putchar(ch) == EOF) 2264b88c807SRodney W. Grimes break; 2274b88c807SRodney W. Grimes } 2284b88c807SRodney W. Grimes if (ferror(fp)) { 2294b88c807SRodney W. Grimes warn("%s", filename); 230001aff9fSBruce Evans rval = 1; 2314b88c807SRodney W. Grimes clearerr(fp); 2324b88c807SRodney W. Grimes } 2334b88c807SRodney W. Grimes if (ferror(stdout)) 2344b88c807SRodney W. Grimes err(1, "stdout"); 2354b88c807SRodney W. Grimes } 2364b88c807SRodney W. Grimes 237cbf2d71fSMatthew Dillon static void 23878a3801dSWarner Losh raw_cat(int rfd) 2394b88c807SRodney W. Grimes { 24078a3801dSWarner Losh int off, wfd; 241a5da0999SWarner Losh ssize_t nr, nw; 242a5da0999SWarner Losh static size_t bsize; 2439afa09cdSMark Murray static char *buf = NULL; 2444b88c807SRodney W. Grimes struct stat sbuf; 2454b88c807SRodney W. Grimes 2464b88c807SRodney W. Grimes wfd = fileno(stdout); 2474b88c807SRodney W. Grimes if (buf == NULL) { 2484b88c807SRodney W. Grimes if (fstat(wfd, &sbuf)) 2494b88c807SRodney W. Grimes err(1, "%s", filename); 2504b88c807SRodney W. Grimes bsize = MAX(sbuf.st_blksize, 1024); 251d1762d1fSWarner Losh if ((buf = malloc(bsize)) == NULL) 2522192b407SJeroen Ruigrok van der Werven err(1, "buffer"); 2534b88c807SRodney W. Grimes } 2544b88c807SRodney W. Grimes while ((nr = read(rfd, buf, bsize)) > 0) 2554b88c807SRodney W. Grimes for (off = 0; nr; nr -= nw, off += nw) 256a5da0999SWarner Losh if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 2574b88c807SRodney W. Grimes err(1, "stdout"); 258001aff9fSBruce Evans if (nr < 0) { 2594b88c807SRodney W. Grimes warn("%s", filename); 260001aff9fSBruce Evans rval = 1; 261001aff9fSBruce Evans } 2624b88c807SRodney W. Grimes } 263cbf2d71fSMatthew Dillon 264cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 265cbf2d71fSMatthew Dillon 266cbf2d71fSMatthew Dillon static int 26778a3801dSWarner Losh udom_open(const char *path, int flags) 268cbf2d71fSMatthew Dillon { 269cbf2d71fSMatthew Dillon struct sockaddr_un sou; 270cbf2d71fSMatthew Dillon int fd; 2719afa09cdSMark Murray unsigned int len; 272cbf2d71fSMatthew Dillon 273cbf2d71fSMatthew Dillon bzero(&sou, sizeof(sou)); 274cbf2d71fSMatthew Dillon 275cbf2d71fSMatthew Dillon /* 276cbf2d71fSMatthew Dillon * Construct the unix domain socket address and attempt to connect 277cbf2d71fSMatthew Dillon */ 2789afa09cdSMark Murray fd = socket(AF_UNIX, SOCK_STREAM, 0); 2799afa09cdSMark Murray if (fd >= 0) { 280cbf2d71fSMatthew Dillon sou.sun_family = AF_UNIX; 28188485b4aSTim J. Robbins if ((len = strlcpy(sou.sun_path, path, 28288485b4aSTim J. Robbins sizeof(sou.sun_path))) >= sizeof(sou.sun_path)) { 28388485b4aSTim J. Robbins errno = ENAMETOOLONG; 28488485b4aSTim J. Robbins return (-1); 28588485b4aSTim J. Robbins } 286cbf2d71fSMatthew Dillon len = offsetof(struct sockaddr_un, sun_path[len+1]); 287cbf2d71fSMatthew Dillon 288cbf2d71fSMatthew Dillon if (connect(fd, (void *)&sou, len) < 0) { 289cbf2d71fSMatthew Dillon close(fd); 290cbf2d71fSMatthew Dillon fd = -1; 291cbf2d71fSMatthew Dillon } 292cbf2d71fSMatthew Dillon } 293cbf2d71fSMatthew Dillon 294cbf2d71fSMatthew Dillon /* 295cbf2d71fSMatthew Dillon * handle the open flags by shutting down appropriate directions 296cbf2d71fSMatthew Dillon */ 297cbf2d71fSMatthew Dillon if (fd >= 0) { 298cbf2d71fSMatthew Dillon switch(flags & O_ACCMODE) { 299cbf2d71fSMatthew Dillon case O_RDONLY: 3009afa09cdSMark Murray if (shutdown(fd, SHUT_WR) == -1) 3012c61418dSTim J. Robbins warn(NULL); 302cbf2d71fSMatthew Dillon break; 303cbf2d71fSMatthew Dillon case O_WRONLY: 3049afa09cdSMark Murray if (shutdown(fd, SHUT_RD) == -1) 3052c61418dSTim J. Robbins warn(NULL); 306cbf2d71fSMatthew Dillon break; 307cbf2d71fSMatthew Dillon default: 308cbf2d71fSMatthew Dillon break; 309cbf2d71fSMatthew Dillon } 310cbf2d71fSMatthew Dillon } 311cbf2d71fSMatthew Dillon return(fd); 312cbf2d71fSMatthew Dillon } 313cbf2d71fSMatthew Dillon 314cbf2d71fSMatthew Dillon #endif 315