19ddb49cbSWarner Losh /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 44b88c807SRodney W. Grimes * Copyright (c) 1989, 1993 54b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 64b88c807SRodney W. Grimes * 74b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 84b88c807SRodney W. Grimes * Kevin Fall. 94b88c807SRodney W. Grimes * 104b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 114b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 124b88c807SRodney W. Grimes * are met: 134b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 154b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 164b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 174b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 194b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 204b88c807SRodney W. Grimes * without specific prior written permission. 214b88c807SRodney W. Grimes * 224b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 234b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 244b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 254b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 264b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 274b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 284b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 294b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 304b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 314b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 324b88c807SRodney W. Grimes * SUCH DAMAGE. 334b88c807SRodney W. Grimes */ 344b88c807SRodney W. Grimes 350d22cdf0SDavid E. O'Brien #if 0 364b88c807SRodney W. Grimes #ifndef lint 37890acb95SSteve Price static char const copyright[] = 384b88c807SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 394b88c807SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 404b88c807SRodney W. Grimes #endif /* not lint */ 410d22cdf0SDavid E. O'Brien #endif 424b88c807SRodney W. Grimes 434b88c807SRodney W. Grimes #ifndef lint 444c95995fSPhilippe Charnier #if 0 4512f93eb9SPhilippe Charnier static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; 464c95995fSPhilippe Charnier #endif 474b88c807SRodney W. Grimes #endif /* not lint */ 485eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 495eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 504b88c807SRodney W. Grimes 51*aefe30c5SMariusz Zaborski #include <sys/capsicum.h> 524b88c807SRodney W. Grimes #include <sys/param.h> 534b88c807SRodney W. Grimes #include <sys/stat.h> 54cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 55cbf2d71fSMatthew Dillon #include <sys/socket.h> 56cbf2d71fSMatthew Dillon #include <sys/un.h> 571c9fbb5aSHiroki Sato #include <netdb.h> 58cbf2d71fSMatthew Dillon #endif 594b88c807SRodney W. Grimes 60*aefe30c5SMariusz Zaborski #include <capsicum_helpers.h> 614b88c807SRodney W. Grimes #include <ctype.h> 624b88c807SRodney W. Grimes #include <err.h> 634be62405SEd Maste #include <errno.h> 644b88c807SRodney W. Grimes #include <fcntl.h> 653043192bSAndrey A. Chernov #include <locale.h> 664b88c807SRodney W. Grimes #include <stdio.h> 674b88c807SRodney W. Grimes #include <stdlib.h> 68cafefe8cSDima Dorfman #include <string.h> 694b88c807SRodney W. Grimes #include <unistd.h> 702aa6b16fSAndrey A. Chernov #include <wchar.h> 712aa6b16fSAndrey A. Chernov #include <wctype.h> 724b88c807SRodney W. Grimes 73*aefe30c5SMariusz Zaborski #include <libcasper.h> 74*aefe30c5SMariusz Zaborski #include <casper/cap_fileargs.h> 75*aefe30c5SMariusz Zaborski #include <casper/cap_net.h> 76*aefe30c5SMariusz Zaborski 77aece80a2SBrooks Davis static int bflag, eflag, lflag, nflag, sflag, tflag, vflag; 78f9d4afb4SEd Schouten static int rval; 79f9d4afb4SEd Schouten static const char *filename; 80*aefe30c5SMariusz Zaborski static fileargs_t *fa; 814b88c807SRodney W. Grimes 82e99f8bc0SEitan Adler static void usage(void) __dead2; 839d32ecfcSMark Murray static void scanfiles(char *argv[], int cooked); 84ed845580SAlex Richardson #ifndef BOOTSTRAP_CAT 8578a3801dSWarner Losh static void cook_cat(FILE *); 86ed845580SAlex Richardson #endif 8778a3801dSWarner Losh static void raw_cat(int); 88cbf2d71fSMatthew Dillon 89cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 90*aefe30c5SMariusz Zaborski static cap_channel_t *capnet; 91*aefe30c5SMariusz Zaborski 9278a3801dSWarner Losh static int udom_open(const char *path, int flags); 93cbf2d71fSMatthew Dillon #endif 944b88c807SRodney W. Grimes 9567bf019bSJaakko Heinonen /* 9667bf019bSJaakko Heinonen * Memory strategy threshold, in pages: if physmem is larger than this, 9767bf019bSJaakko Heinonen * use a large buffer. 9867bf019bSJaakko Heinonen */ 99e9cbc9a7SIvan Voras #define PHYSPAGES_THRESHOLD (32 * 1024) 100e9cbc9a7SIvan Voras 10167bf019bSJaakko Heinonen /* Maximum buffer size in bytes - do not allow it to grow larger than this. */ 102e9cbc9a7SIvan Voras #define BUFSIZE_MAX (2 * 1024 * 1024) 103e9cbc9a7SIvan Voras 10467bf019bSJaakko Heinonen /* 10567bf019bSJaakko Heinonen * Small (default) buffer size in bytes. It's inefficient for this to be 10667bf019bSJaakko Heinonen * smaller than MAXPHYS. 10767bf019bSJaakko Heinonen */ 108e9cbc9a7SIvan Voras #define BUFSIZE_SMALL (MAXPHYS) 109e9cbc9a7SIvan Voras 110a33ee411SAlex Richardson 111a33ee411SAlex Richardson /* 112a33ee411SAlex Richardson * For the bootstrapped cat binary (needed for locked appending to METALOG), we 113a33ee411SAlex Richardson * disable all flags except -l and -u to avoid non-portable function calls. 114a33ee411SAlex Richardson * In the future we may instead want to write a small portable bootstrap tool 115a33ee411SAlex Richardson * that locks the output file before writing to it. However, for now 116a33ee411SAlex Richardson * bootstrapping cat without multibyte support is the simpler solution. 117a33ee411SAlex Richardson */ 118a33ee411SAlex Richardson #ifdef BOOTSTRAP_CAT 119a33ee411SAlex Richardson #define SUPPORTED_FLAGS "lu" 120a33ee411SAlex Richardson #else 121a33ee411SAlex Richardson #define SUPPORTED_FLAGS "belnstuv" 122a33ee411SAlex Richardson #endif 123a33ee411SAlex Richardson 124*aefe30c5SMariusz Zaborski #ifndef NO_UDOM_SUPPORT 125*aefe30c5SMariusz Zaborski static void 126*aefe30c5SMariusz Zaborski init_casper_net(cap_channel_t *casper) 127*aefe30c5SMariusz Zaborski { 128*aefe30c5SMariusz Zaborski cap_net_limit_t *limit; 129*aefe30c5SMariusz Zaborski int familylimit; 130*aefe30c5SMariusz Zaborski 131*aefe30c5SMariusz Zaborski capnet = cap_service_open(casper, "system.net"); 132*aefe30c5SMariusz Zaborski if (capnet == NULL) 133*aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to create network service"); 134*aefe30c5SMariusz Zaborski 135*aefe30c5SMariusz Zaborski limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR | 136*aefe30c5SMariusz Zaborski CAPNET_CONNECTDNS); 137*aefe30c5SMariusz Zaborski if (limit == NULL) 138*aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to create limits"); 139*aefe30c5SMariusz Zaborski 140*aefe30c5SMariusz Zaborski familylimit = AF_LOCAL; 141*aefe30c5SMariusz Zaborski cap_net_limit_name2addr_family(limit, &familylimit, 1); 142*aefe30c5SMariusz Zaborski 143*aefe30c5SMariusz Zaborski if (cap_net_limit(limit) < 0) 144*aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to apply limits"); 145*aefe30c5SMariusz Zaborski } 146*aefe30c5SMariusz Zaborski #endif 147*aefe30c5SMariusz Zaborski 148*aefe30c5SMariusz Zaborski static void 149*aefe30c5SMariusz Zaborski init_casper(int argc, char *argv[]) 150*aefe30c5SMariusz Zaborski { 151*aefe30c5SMariusz Zaborski cap_channel_t *casper; 152*aefe30c5SMariusz Zaborski cap_rights_t rights; 153*aefe30c5SMariusz Zaborski 154*aefe30c5SMariusz Zaborski casper = cap_init(); 155*aefe30c5SMariusz Zaborski if (casper == NULL) 156*aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to create Casper"); 157*aefe30c5SMariusz Zaborski 158*aefe30c5SMariusz Zaborski fa = fileargs_cinit(casper, argc, argv, O_RDONLY, 0, 159*aefe30c5SMariusz Zaborski cap_rights_init(&rights, CAP_READ | CAP_FSTAT | CAP_FCNTL), 160*aefe30c5SMariusz Zaborski FA_OPEN | FA_REALPATH); 161*aefe30c5SMariusz Zaborski if (fa == NULL) 162*aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to create fileargs"); 163*aefe30c5SMariusz Zaborski 164*aefe30c5SMariusz Zaborski #ifndef NO_UDOM_SUPPORT 165*aefe30c5SMariusz Zaborski init_casper_net(casper); 166*aefe30c5SMariusz Zaborski #endif 167*aefe30c5SMariusz Zaborski 168*aefe30c5SMariusz Zaborski cap_close(casper); 169*aefe30c5SMariusz Zaborski } 170*aefe30c5SMariusz Zaborski 1714b88c807SRodney W. Grimes int 17278a3801dSWarner Losh main(int argc, char *argv[]) 1734b88c807SRodney W. Grimes { 1744b88c807SRodney W. Grimes int ch; 175aece80a2SBrooks Davis struct flock stdout_lock; 1764b88c807SRodney W. Grimes 1773043192bSAndrey A. Chernov setlocale(LC_CTYPE, ""); 1783043192bSAndrey A. Chernov 179a33ee411SAlex Richardson while ((ch = getopt(argc, argv, SUPPORTED_FLAGS)) != -1) 1804b88c807SRodney W. Grimes switch (ch) { 1814b88c807SRodney W. Grimes case 'b': 1824b88c807SRodney W. Grimes bflag = nflag = 1; /* -b implies -n */ 1834b88c807SRodney W. Grimes break; 1844b88c807SRodney W. Grimes case 'e': 1854b88c807SRodney W. Grimes eflag = vflag = 1; /* -e implies -v */ 1864b88c807SRodney W. Grimes break; 187aece80a2SBrooks Davis case 'l': 188aece80a2SBrooks Davis lflag = 1; 189aece80a2SBrooks Davis break; 1904b88c807SRodney W. Grimes case 'n': 1914b88c807SRodney W. Grimes nflag = 1; 1924b88c807SRodney W. Grimes break; 1934b88c807SRodney W. Grimes case 's': 1944b88c807SRodney W. Grimes sflag = 1; 1954b88c807SRodney W. Grimes break; 1964b88c807SRodney W. Grimes case 't': 1974b88c807SRodney W. Grimes tflag = vflag = 1; /* -t implies -v */ 1984b88c807SRodney W. Grimes break; 1994b88c807SRodney W. Grimes case 'u': 2002192b407SJeroen Ruigrok van der Werven setbuf(stdout, NULL); 2014b88c807SRodney W. Grimes break; 2024b88c807SRodney W. Grimes case 'v': 2034b88c807SRodney W. Grimes vflag = 1; 2044b88c807SRodney W. Grimes break; 2058d72a3d7SWarner Losh default: 206ca2be2ffSJuli Mallett usage(); 2074b88c807SRodney W. Grimes } 2084b88c807SRodney W. Grimes argv += optind; 209*aefe30c5SMariusz Zaborski argc -= optind; 2104b88c807SRodney W. Grimes 211aece80a2SBrooks Davis if (lflag) { 212aece80a2SBrooks Davis stdout_lock.l_len = 0; 213aece80a2SBrooks Davis stdout_lock.l_start = 0; 214aece80a2SBrooks Davis stdout_lock.l_type = F_WRLCK; 215aece80a2SBrooks Davis stdout_lock.l_whence = SEEK_SET; 216aece80a2SBrooks Davis if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1) 217aece80a2SBrooks Davis err(EXIT_FAILURE, "stdout"); 218aece80a2SBrooks Davis } 219aece80a2SBrooks Davis 220*aefe30c5SMariusz Zaborski init_casper(argc, argv); 221*aefe30c5SMariusz Zaborski 222*aefe30c5SMariusz Zaborski caph_cache_catpages(); 223*aefe30c5SMariusz Zaborski 224*aefe30c5SMariusz Zaborski if (caph_enter_casper() < 0) 225*aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "capsicum"); 226*aefe30c5SMariusz Zaborski 2274b88c807SRodney W. Grimes if (bflag || eflag || nflag || sflag || tflag || vflag) 228cbf2d71fSMatthew Dillon scanfiles(argv, 1); 2294b88c807SRodney W. Grimes else 230cbf2d71fSMatthew Dillon scanfiles(argv, 0); 2314b88c807SRodney W. Grimes if (fclose(stdout)) 2324b88c807SRodney W. Grimes err(1, "stdout"); 2334b88c807SRodney W. Grimes exit(rval); 2349f82c1d3SMark Murray /* NOTREACHED */ 2354b88c807SRodney W. Grimes } 2364b88c807SRodney W. Grimes 237ca2be2ffSJuli Mallett static void 238ca2be2ffSJuli Mallett usage(void) 239ca2be2ffSJuli Mallett { 240e99f8bc0SEitan Adler 241a33ee411SAlex Richardson fprintf(stderr, "usage: cat [-" SUPPORTED_FLAGS "] [file ...]\n"); 242ca2be2ffSJuli Mallett exit(1); 2439f82c1d3SMark Murray /* NOTREACHED */ 244ca2be2ffSJuli Mallett } 245ca2be2ffSJuli Mallett 2469d32ecfcSMark Murray static void 247ed845580SAlex Richardson scanfiles(char *argv[], int cooked __unused) 2484b88c807SRodney W. Grimes { 24967bf019bSJaakko Heinonen int fd, i; 250cbf2d71fSMatthew Dillon char *path; 251ed845580SAlex Richardson #ifndef BOOTSTRAP_CAT 2521b00c916SRuslan Ermilov FILE *fp; 253ed845580SAlex Richardson #endif 2544b88c807SRodney W. Grimes 25567bf019bSJaakko Heinonen i = 0; 25619271eb4SBryan Drewery fd = -1; 257cbf2d71fSMatthew Dillon while ((path = argv[i]) != NULL || i == 0) { 258cbf2d71fSMatthew Dillon if (path == NULL || strcmp(path, "-") == 0) { 2594b88c807SRodney W. Grimes filename = "stdin"; 2601b00c916SRuslan Ermilov fd = STDIN_FILENO; 261cbf2d71fSMatthew Dillon } else { 262cbf2d71fSMatthew Dillon filename = path; 263*aefe30c5SMariusz Zaborski fd = fileargs_open(fa, path); 264cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 265cbf2d71fSMatthew Dillon if (fd < 0 && errno == EOPNOTSUPP) 26643e09ab2SRuslan Ermilov fd = udom_open(path, O_RDONLY); 267cbf2d71fSMatthew Dillon #endif 268cbf2d71fSMatthew Dillon } 269cbf2d71fSMatthew Dillon if (fd < 0) { 270cbf2d71fSMatthew Dillon warn("%s", path); 271001aff9fSBruce Evans rval = 1; 272a33ee411SAlex Richardson #ifndef BOOTSTRAP_CAT 273cbf2d71fSMatthew Dillon } else if (cooked) { 2741b00c916SRuslan Ermilov if (fd == STDIN_FILENO) 2751b00c916SRuslan Ermilov cook_cat(stdin); 2761b00c916SRuslan Ermilov else { 2771b00c916SRuslan Ermilov fp = fdopen(fd, "r"); 278cbf2d71fSMatthew Dillon cook_cat(fp); 279cbf2d71fSMatthew Dillon fclose(fp); 2801b00c916SRuslan Ermilov } 281a33ee411SAlex Richardson #endif 282cbf2d71fSMatthew Dillon } else { 283cbf2d71fSMatthew Dillon raw_cat(fd); 2841b00c916SRuslan Ermilov if (fd != STDIN_FILENO) 285cbf2d71fSMatthew Dillon close(fd); 2864b88c807SRodney W. Grimes } 287cbf2d71fSMatthew Dillon if (path == NULL) 288cbf2d71fSMatthew Dillon break; 289cbf2d71fSMatthew Dillon ++i; 2904b88c807SRodney W. Grimes } 2914b88c807SRodney W. Grimes } 2924b88c807SRodney W. Grimes 293a33ee411SAlex Richardson #ifndef BOOTSTRAP_CAT 294cbf2d71fSMatthew Dillon static void 29578a3801dSWarner Losh cook_cat(FILE *fp) 2964b88c807SRodney W. Grimes { 29778a3801dSWarner Losh int ch, gobble, line, prev; 2982aa6b16fSAndrey A. Chernov wint_t wch; 2994b88c807SRodney W. Grimes 3001b00c916SRuslan Ermilov /* Reset EOF condition on stdin. */ 3011b00c916SRuslan Ermilov if (fp == stdin && feof(stdin)) 3021b00c916SRuslan Ermilov clearerr(stdin); 3031b00c916SRuslan Ermilov 3044b88c807SRodney W. Grimes line = gobble = 0; 3054b88c807SRodney W. Grimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 3064b88c807SRodney W. Grimes if (prev == '\n') { 3074b88c807SRodney W. Grimes if (sflag) { 3084b88c807SRodney W. Grimes if (ch == '\n') { 309bf5f0c44STim J. Robbins if (gobble) 310bf5f0c44STim J. Robbins continue; 311bf5f0c44STim J. Robbins gobble = 1; 312bf5f0c44STim J. Robbins } else 313bf5f0c44STim J. Robbins gobble = 0; 314bf5f0c44STim J. Robbins } 3156d2e5f3dSSevan Janiyan if (nflag) { 3166d2e5f3dSSevan Janiyan if (!bflag || ch != '\n') { 317bf5f0c44STim J. Robbins (void)fprintf(stdout, "%6d\t", ++line); 318bf5f0c44STim J. Robbins if (ferror(stdout)) 319bf5f0c44STim J. Robbins break; 3206d2e5f3dSSevan Janiyan } else if (eflag) { 3216d2e5f3dSSevan Janiyan (void)fprintf(stdout, "%6s\t", ""); 3226d2e5f3dSSevan Janiyan if (ferror(stdout)) 3236d2e5f3dSSevan Janiyan break; 3246d2e5f3dSSevan Janiyan } 325bf5f0c44STim J. Robbins } 326bf5f0c44STim J. Robbins } 327bf5f0c44STim J. Robbins if (ch == '\n') { 328bf5f0c44STim J. Robbins if (eflag && putchar('$') == EOF) 3294b88c807SRodney W. Grimes break; 3304b88c807SRodney W. Grimes } else if (ch == '\t') { 3314b88c807SRodney W. Grimes if (tflag) { 3324b88c807SRodney W. Grimes if (putchar('^') == EOF || putchar('I') == EOF) 3334b88c807SRodney W. Grimes break; 3344b88c807SRodney W. Grimes continue; 3354b88c807SRodney W. Grimes } 3364b88c807SRodney W. Grimes } else if (vflag) { 3372aa6b16fSAndrey A. Chernov (void)ungetc(ch, fp); 3382aa6b16fSAndrey A. Chernov /* 3392aa6b16fSAndrey A. Chernov * Our getwc(3) doesn't change file position 3402aa6b16fSAndrey A. Chernov * on error. 3412aa6b16fSAndrey A. Chernov */ 3422aa6b16fSAndrey A. Chernov if ((wch = getwc(fp)) == WEOF) { 3432aa6b16fSAndrey A. Chernov if (ferror(fp) && errno == EILSEQ) { 3442aa6b16fSAndrey A. Chernov clearerr(fp); 3452aa6b16fSAndrey A. Chernov /* Resync attempt. */ 3462aa6b16fSAndrey A. Chernov memset(&fp->_mbstate, 0, sizeof(mbstate_t)); 3472aa6b16fSAndrey A. Chernov if ((ch = getc(fp)) == EOF) 3482aa6b16fSAndrey A. Chernov break; 3492aa6b16fSAndrey A. Chernov wch = ch; 3502aa6b16fSAndrey A. Chernov goto ilseq; 3512aa6b16fSAndrey A. Chernov } else 3522aa6b16fSAndrey A. Chernov break; 3532aa6b16fSAndrey A. Chernov } 3542aa6b16fSAndrey A. Chernov if (!iswascii(wch) && !iswprint(wch)) { 3552aa6b16fSAndrey A. Chernov ilseq: 3564b88c807SRodney W. Grimes if (putchar('M') == EOF || putchar('-') == EOF) 3574b88c807SRodney W. Grimes break; 3582aa6b16fSAndrey A. Chernov wch = toascii(wch); 3594b88c807SRodney W. Grimes } 3602aa6b16fSAndrey A. Chernov if (iswcntrl(wch)) { 3612aa6b16fSAndrey A. Chernov ch = toascii(wch); 3622aa6b16fSAndrey A. Chernov ch = (ch == '\177') ? '?' : (ch | 0100); 3632aa6b16fSAndrey A. Chernov if (putchar('^') == EOF || putchar(ch) == EOF) 3644b88c807SRodney W. Grimes break; 3654b88c807SRodney W. Grimes continue; 3664b88c807SRodney W. Grimes } 3672aa6b16fSAndrey A. Chernov if (putwchar(wch) == WEOF) 3682aa6b16fSAndrey A. Chernov break; 3692aa6b16fSAndrey A. Chernov ch = -1; 3702aa6b16fSAndrey A. Chernov continue; 3714b88c807SRodney W. Grimes } 3724b88c807SRodney W. Grimes if (putchar(ch) == EOF) 3734b88c807SRodney W. Grimes break; 3744b88c807SRodney W. Grimes } 3754b88c807SRodney W. Grimes if (ferror(fp)) { 3764b88c807SRodney W. Grimes warn("%s", filename); 377001aff9fSBruce Evans rval = 1; 3784b88c807SRodney W. Grimes clearerr(fp); 3794b88c807SRodney W. Grimes } 3804b88c807SRodney W. Grimes if (ferror(stdout)) 3814b88c807SRodney W. Grimes err(1, "stdout"); 3824b88c807SRodney W. Grimes } 383a33ee411SAlex Richardson #endif /* BOOTSTRAP_CAT */ 3844b88c807SRodney W. Grimes 385cbf2d71fSMatthew Dillon static void 38678a3801dSWarner Losh raw_cat(int rfd) 3874b88c807SRodney W. Grimes { 388ca23e64eSWarner Losh long pagesize; 38978a3801dSWarner Losh int off, wfd; 390a5da0999SWarner Losh ssize_t nr, nw; 391a5da0999SWarner Losh static size_t bsize; 3929afa09cdSMark Murray static char *buf = NULL; 3934b88c807SRodney W. Grimes struct stat sbuf; 3944b88c807SRodney W. Grimes 3954b88c807SRodney W. Grimes wfd = fileno(stdout); 3964b88c807SRodney W. Grimes if (buf == NULL) { 3974b88c807SRodney W. Grimes if (fstat(wfd, &sbuf)) 398e3481b29SJaakko Heinonen err(1, "stdout"); 399e9cbc9a7SIvan Voras if (S_ISREG(sbuf.st_mode)) { 400e9cbc9a7SIvan Voras /* If there's plenty of RAM, use a large copy buffer */ 401e9cbc9a7SIvan Voras if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD) 402e9cbc9a7SIvan Voras bsize = MIN(BUFSIZE_MAX, MAXPHYS * 8); 403e9cbc9a7SIvan Voras else 404e9cbc9a7SIvan Voras bsize = BUFSIZE_SMALL; 405ca23e64eSWarner Losh } else { 406ca23e64eSWarner Losh bsize = sbuf.st_blksize; 407ca23e64eSWarner Losh pagesize = sysconf(_SC_PAGESIZE); 408ca23e64eSWarner Losh if (pagesize > 0) 409ca23e64eSWarner Losh bsize = MAX(bsize, (size_t)pagesize); 410ca23e64eSWarner Losh } 411d1762d1fSWarner Losh if ((buf = malloc(bsize)) == NULL) 412e9cbc9a7SIvan Voras err(1, "malloc() failure of IO buffer"); 4134b88c807SRodney W. Grimes } 4144b88c807SRodney W. Grimes while ((nr = read(rfd, buf, bsize)) > 0) 4154b88c807SRodney W. Grimes for (off = 0; nr; nr -= nw, off += nw) 416a5da0999SWarner Losh if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 4174b88c807SRodney W. Grimes err(1, "stdout"); 418001aff9fSBruce Evans if (nr < 0) { 4194b88c807SRodney W. Grimes warn("%s", filename); 420001aff9fSBruce Evans rval = 1; 421001aff9fSBruce Evans } 4224b88c807SRodney W. Grimes } 423cbf2d71fSMatthew Dillon 424cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 425cbf2d71fSMatthew Dillon 426cbf2d71fSMatthew Dillon static int 42778a3801dSWarner Losh udom_open(const char *path, int flags) 428cbf2d71fSMatthew Dillon { 4291c9fbb5aSHiroki Sato struct addrinfo hints, *res, *res0; 4301c9fbb5aSHiroki Sato char rpath[PATH_MAX]; 43164c7af10SSean Bruno int fd = -1; 43264c7af10SSean Bruno int error; 433*aefe30c5SMariusz Zaborski cap_rights_t rights; 434cbf2d71fSMatthew Dillon 435cbf2d71fSMatthew Dillon /* 4361c9fbb5aSHiroki Sato * Construct the unix domain socket address and attempt to connect. 437cbf2d71fSMatthew Dillon */ 4381c9fbb5aSHiroki Sato bzero(&hints, sizeof(hints)); 4391c9fbb5aSHiroki Sato hints.ai_family = AF_LOCAL; 440*aefe30c5SMariusz Zaborski 441*aefe30c5SMariusz Zaborski if (fileargs_realpath(fa, path, rpath) == NULL) 4421c9fbb5aSHiroki Sato return (-1); 443*aefe30c5SMariusz Zaborski 444*aefe30c5SMariusz Zaborski error = cap_getaddrinfo(capnet, rpath, NULL, &hints, &res0); 4451c9fbb5aSHiroki Sato if (error) { 4461c9fbb5aSHiroki Sato warn("%s", gai_strerror(error)); 4471c9fbb5aSHiroki Sato errno = EINVAL; 44888485b4aSTim J. Robbins return (-1); 44988485b4aSTim J. Robbins } 450*aefe30c5SMariusz Zaborski cap_rights_init(&rights, CAP_CONNECT, CAP_READ, CAP_WRITE, 451*aefe30c5SMariusz Zaborski CAP_SHUTDOWN, CAP_FSTAT, CAP_FCNTL); 4521c9fbb5aSHiroki Sato for (res = res0; res != NULL; res = res->ai_next) { 4531c9fbb5aSHiroki Sato fd = socket(res->ai_family, res->ai_socktype, 4541c9fbb5aSHiroki Sato res->ai_protocol); 4551c9fbb5aSHiroki Sato if (fd < 0) { 4561c9fbb5aSHiroki Sato freeaddrinfo(res0); 4571c9fbb5aSHiroki Sato return (-1); 4581c9fbb5aSHiroki Sato } 459*aefe30c5SMariusz Zaborski if (caph_rights_limit(fd, &rights) < 0) { 460*aefe30c5SMariusz Zaborski close(fd); 461*aefe30c5SMariusz Zaborski return (-1); 462*aefe30c5SMariusz Zaborski } 463*aefe30c5SMariusz Zaborski error = cap_connect(capnet, fd, res->ai_addr, res->ai_addrlen); 4641c9fbb5aSHiroki Sato if (error == 0) 4651c9fbb5aSHiroki Sato break; 4661c9fbb5aSHiroki Sato else { 467cbf2d71fSMatthew Dillon close(fd); 468cbf2d71fSMatthew Dillon fd = -1; 469cbf2d71fSMatthew Dillon } 470cbf2d71fSMatthew Dillon } 4711c9fbb5aSHiroki Sato freeaddrinfo(res0); 472cbf2d71fSMatthew Dillon 473cbf2d71fSMatthew Dillon /* 474cbf2d71fSMatthew Dillon * handle the open flags by shutting down appropriate directions 475cbf2d71fSMatthew Dillon */ 476cbf2d71fSMatthew Dillon if (fd >= 0) { 477cbf2d71fSMatthew Dillon switch(flags & O_ACCMODE) { 478cbf2d71fSMatthew Dillon case O_RDONLY: 479*aefe30c5SMariusz Zaborski cap_rights_clear(&rights, CAP_WRITE); 4809afa09cdSMark Murray if (shutdown(fd, SHUT_WR) == -1) 4812c61418dSTim J. Robbins warn(NULL); 482cbf2d71fSMatthew Dillon break; 483cbf2d71fSMatthew Dillon case O_WRONLY: 484*aefe30c5SMariusz Zaborski cap_rights_clear(&rights, CAP_READ); 4859afa09cdSMark Murray if (shutdown(fd, SHUT_RD) == -1) 4862c61418dSTim J. Robbins warn(NULL); 487cbf2d71fSMatthew Dillon break; 488cbf2d71fSMatthew Dillon default: 489cbf2d71fSMatthew Dillon break; 490cbf2d71fSMatthew Dillon } 491*aefe30c5SMariusz Zaborski 492*aefe30c5SMariusz Zaborski cap_rights_clear(&rights, CAP_CONNECT, CAP_SHUTDOWN); 493*aefe30c5SMariusz Zaborski if (caph_rights_limit(fd, &rights) < 0) { 494*aefe30c5SMariusz Zaborski close(fd); 495*aefe30c5SMariusz Zaborski return (-1); 496*aefe30c5SMariusz Zaborski } 497cbf2d71fSMatthew Dillon } 498cbf2d71fSMatthew Dillon return (fd); 499cbf2d71fSMatthew Dillon } 500cbf2d71fSMatthew Dillon 501cbf2d71fSMatthew Dillon #endif 502