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 35aefe30c5SMariusz Zaborski #include <sys/capsicum.h> 364b88c807SRodney W. Grimes #include <sys/param.h> 374b88c807SRodney W. Grimes #include <sys/stat.h> 38cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 39cbf2d71fSMatthew Dillon #include <sys/socket.h> 40cbf2d71fSMatthew Dillon #include <sys/un.h> 411c9fbb5aSHiroki Sato #include <netdb.h> 42cbf2d71fSMatthew Dillon #endif 434b88c807SRodney W. Grimes 44aefe30c5SMariusz Zaborski #include <capsicum_helpers.h> 454b88c807SRodney W. Grimes #include <ctype.h> 464b88c807SRodney W. Grimes #include <err.h> 474be62405SEd Maste #include <errno.h> 484b88c807SRodney W. Grimes #include <fcntl.h> 493043192bSAndrey A. Chernov #include <locale.h> 504b88c807SRodney W. Grimes #include <stdio.h> 514b88c807SRodney W. Grimes #include <stdlib.h> 52cafefe8cSDima Dorfman #include <string.h> 534b88c807SRodney W. Grimes #include <unistd.h> 542aa6b16fSAndrey A. Chernov #include <wchar.h> 552aa6b16fSAndrey A. Chernov #include <wctype.h> 564b88c807SRodney W. Grimes 57aefe30c5SMariusz Zaborski #include <libcasper.h> 58aefe30c5SMariusz Zaborski #include <casper/cap_fileargs.h> 59aefe30c5SMariusz Zaborski #include <casper/cap_net.h> 60aefe30c5SMariusz Zaborski 61aece80a2SBrooks Davis static int bflag, eflag, lflag, nflag, sflag, tflag, vflag; 62f9d4afb4SEd Schouten static int rval; 63f9d4afb4SEd Schouten static const char *filename; 64aefe30c5SMariusz Zaborski static fileargs_t *fa; 654b88c807SRodney W. Grimes 66e99f8bc0SEitan Adler static void usage(void) __dead2; 679d32ecfcSMark Murray static void scanfiles(char *argv[], int cooked); 68ed845580SAlex Richardson #ifndef BOOTSTRAP_CAT 6978a3801dSWarner Losh static void cook_cat(FILE *); 708113cc82SMartin Matuska static ssize_t in_kernel_copy(int); 71ed845580SAlex Richardson #endif 7278a3801dSWarner Losh static void raw_cat(int); 73cbf2d71fSMatthew Dillon 74cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 75aefe30c5SMariusz Zaborski static cap_channel_t *capnet; 76aefe30c5SMariusz Zaborski 7778a3801dSWarner Losh static int udom_open(const char *path, int flags); 78cbf2d71fSMatthew Dillon #endif 794b88c807SRodney W. Grimes 8067bf019bSJaakko Heinonen /* 8167bf019bSJaakko Heinonen * Memory strategy threshold, in pages: if physmem is larger than this, 8267bf019bSJaakko Heinonen * use a large buffer. 8367bf019bSJaakko Heinonen */ 84e9cbc9a7SIvan Voras #define PHYSPAGES_THRESHOLD (32 * 1024) 85e9cbc9a7SIvan Voras 8667bf019bSJaakko Heinonen /* Maximum buffer size in bytes - do not allow it to grow larger than this. */ 87e9cbc9a7SIvan Voras #define BUFSIZE_MAX (2 * 1024 * 1024) 88e9cbc9a7SIvan Voras 8967bf019bSJaakko Heinonen /* 9067bf019bSJaakko Heinonen * Small (default) buffer size in bytes. It's inefficient for this to be 9167bf019bSJaakko Heinonen * smaller than MAXPHYS. 9267bf019bSJaakko Heinonen */ 93e9cbc9a7SIvan Voras #define BUFSIZE_SMALL (MAXPHYS) 94e9cbc9a7SIvan Voras 95a33ee411SAlex Richardson 96a33ee411SAlex Richardson /* 97a33ee411SAlex Richardson * For the bootstrapped cat binary (needed for locked appending to METALOG), we 98a33ee411SAlex Richardson * disable all flags except -l and -u to avoid non-portable function calls. 99a33ee411SAlex Richardson * In the future we may instead want to write a small portable bootstrap tool 100a33ee411SAlex Richardson * that locks the output file before writing to it. However, for now 101a33ee411SAlex Richardson * bootstrapping cat without multibyte support is the simpler solution. 102a33ee411SAlex Richardson */ 103a33ee411SAlex Richardson #ifdef BOOTSTRAP_CAT 104a33ee411SAlex Richardson #define SUPPORTED_FLAGS "lu" 105a33ee411SAlex Richardson #else 106a33ee411SAlex Richardson #define SUPPORTED_FLAGS "belnstuv" 107a33ee411SAlex Richardson #endif 108a33ee411SAlex Richardson 109aefe30c5SMariusz Zaborski #ifndef NO_UDOM_SUPPORT 110aefe30c5SMariusz Zaborski static void 111aefe30c5SMariusz Zaborski init_casper_net(cap_channel_t *casper) 112aefe30c5SMariusz Zaborski { 113aefe30c5SMariusz Zaborski cap_net_limit_t *limit; 114aefe30c5SMariusz Zaborski int familylimit; 115aefe30c5SMariusz Zaborski 116aefe30c5SMariusz Zaborski capnet = cap_service_open(casper, "system.net"); 117aefe30c5SMariusz Zaborski if (capnet == NULL) 118aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to create network service"); 119aefe30c5SMariusz Zaborski 120aefe30c5SMariusz Zaborski limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR | 121aefe30c5SMariusz Zaborski CAPNET_CONNECTDNS); 122aefe30c5SMariusz Zaborski if (limit == NULL) 123aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to create limits"); 124aefe30c5SMariusz Zaborski 125aefe30c5SMariusz Zaborski familylimit = AF_LOCAL; 126aefe30c5SMariusz Zaborski cap_net_limit_name2addr_family(limit, &familylimit, 1); 127aefe30c5SMariusz Zaborski 128aefe30c5SMariusz Zaborski if (cap_net_limit(limit) < 0) 129aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to apply limits"); 130aefe30c5SMariusz Zaborski } 131aefe30c5SMariusz Zaborski #endif 132aefe30c5SMariusz Zaborski 133aefe30c5SMariusz Zaborski static void 134aefe30c5SMariusz Zaborski init_casper(int argc, char *argv[]) 135aefe30c5SMariusz Zaborski { 136aefe30c5SMariusz Zaborski cap_channel_t *casper; 137aefe30c5SMariusz Zaborski cap_rights_t rights; 138aefe30c5SMariusz Zaborski 139aefe30c5SMariusz Zaborski casper = cap_init(); 140aefe30c5SMariusz Zaborski if (casper == NULL) 141aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to create Casper"); 142aefe30c5SMariusz Zaborski 143aefe30c5SMariusz Zaborski fa = fileargs_cinit(casper, argc, argv, O_RDONLY, 0, 14405f530f4SEd Maste cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL, CAP_SEEK), 145aefe30c5SMariusz Zaborski FA_OPEN | FA_REALPATH); 146aefe30c5SMariusz Zaborski if (fa == NULL) 147aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "unable to create fileargs"); 148aefe30c5SMariusz Zaborski 149aefe30c5SMariusz Zaborski #ifndef NO_UDOM_SUPPORT 150aefe30c5SMariusz Zaborski init_casper_net(casper); 151aefe30c5SMariusz Zaborski #endif 152aefe30c5SMariusz Zaborski 153aefe30c5SMariusz Zaborski cap_close(casper); 154aefe30c5SMariusz Zaborski } 155aefe30c5SMariusz Zaborski 1564b88c807SRodney W. Grimes int 15778a3801dSWarner Losh main(int argc, char *argv[]) 1584b88c807SRodney W. Grimes { 1594b88c807SRodney W. Grimes int ch; 160aece80a2SBrooks Davis struct flock stdout_lock; 1614b88c807SRodney W. Grimes 1623043192bSAndrey A. Chernov setlocale(LC_CTYPE, ""); 1633043192bSAndrey A. Chernov 164a33ee411SAlex Richardson while ((ch = getopt(argc, argv, SUPPORTED_FLAGS)) != -1) 1654b88c807SRodney W. Grimes switch (ch) { 1664b88c807SRodney W. Grimes case 'b': 1674b88c807SRodney W. Grimes bflag = nflag = 1; /* -b implies -n */ 1684b88c807SRodney W. Grimes break; 1694b88c807SRodney W. Grimes case 'e': 1704b88c807SRodney W. Grimes eflag = vflag = 1; /* -e implies -v */ 1714b88c807SRodney W. Grimes break; 172aece80a2SBrooks Davis case 'l': 173aece80a2SBrooks Davis lflag = 1; 174aece80a2SBrooks Davis break; 1754b88c807SRodney W. Grimes case 'n': 1764b88c807SRodney W. Grimes nflag = 1; 1774b88c807SRodney W. Grimes break; 1784b88c807SRodney W. Grimes case 's': 1794b88c807SRodney W. Grimes sflag = 1; 1804b88c807SRodney W. Grimes break; 1814b88c807SRodney W. Grimes case 't': 1824b88c807SRodney W. Grimes tflag = vflag = 1; /* -t implies -v */ 1834b88c807SRodney W. Grimes break; 1844b88c807SRodney W. Grimes case 'u': 1852192b407SJeroen Ruigrok van der Werven setbuf(stdout, NULL); 1864b88c807SRodney W. Grimes break; 1874b88c807SRodney W. Grimes case 'v': 1884b88c807SRodney W. Grimes vflag = 1; 1894b88c807SRodney W. Grimes break; 1908d72a3d7SWarner Losh default: 191ca2be2ffSJuli Mallett usage(); 1924b88c807SRodney W. Grimes } 1934b88c807SRodney W. Grimes argv += optind; 194aefe30c5SMariusz Zaborski argc -= optind; 1954b88c807SRodney W. Grimes 196aece80a2SBrooks Davis if (lflag) { 197aece80a2SBrooks Davis stdout_lock.l_len = 0; 198aece80a2SBrooks Davis stdout_lock.l_start = 0; 199aece80a2SBrooks Davis stdout_lock.l_type = F_WRLCK; 200aece80a2SBrooks Davis stdout_lock.l_whence = SEEK_SET; 201*c6f9df70SDag-Erling Smørgrav if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) != 0) 202aece80a2SBrooks Davis err(EXIT_FAILURE, "stdout"); 203aece80a2SBrooks Davis } 204aece80a2SBrooks Davis 205aefe30c5SMariusz Zaborski init_casper(argc, argv); 206aefe30c5SMariusz Zaborski 207aefe30c5SMariusz Zaborski caph_cache_catpages(); 208aefe30c5SMariusz Zaborski 209aefe30c5SMariusz Zaborski if (caph_enter_casper() < 0) 210aefe30c5SMariusz Zaborski err(EXIT_FAILURE, "capsicum"); 211aefe30c5SMariusz Zaborski 2124b88c807SRodney W. Grimes if (bflag || eflag || nflag || sflag || tflag || vflag) 213cbf2d71fSMatthew Dillon scanfiles(argv, 1); 2144b88c807SRodney W. Grimes else 215cbf2d71fSMatthew Dillon scanfiles(argv, 0); 2164b88c807SRodney W. Grimes if (fclose(stdout)) 2174b88c807SRodney W. Grimes err(1, "stdout"); 2184b88c807SRodney W. Grimes exit(rval); 2199f82c1d3SMark Murray /* NOTREACHED */ 2204b88c807SRodney W. Grimes } 2214b88c807SRodney W. Grimes 222ca2be2ffSJuli Mallett static void 223ca2be2ffSJuli Mallett usage(void) 224ca2be2ffSJuli Mallett { 225e99f8bc0SEitan Adler 226a33ee411SAlex Richardson fprintf(stderr, "usage: cat [-" SUPPORTED_FLAGS "] [file ...]\n"); 227ca2be2ffSJuli Mallett exit(1); 2289f82c1d3SMark Murray /* NOTREACHED */ 229ca2be2ffSJuli Mallett } 230ca2be2ffSJuli Mallett 2319d32ecfcSMark Murray static void 232ed845580SAlex Richardson scanfiles(char *argv[], int cooked __unused) 2334b88c807SRodney W. Grimes { 23467bf019bSJaakko Heinonen int fd, i; 235cbf2d71fSMatthew Dillon char *path; 236ed845580SAlex Richardson #ifndef BOOTSTRAP_CAT 2371b00c916SRuslan Ermilov FILE *fp; 238ed845580SAlex Richardson #endif 2394b88c807SRodney W. Grimes 24067bf019bSJaakko Heinonen i = 0; 24119271eb4SBryan Drewery fd = -1; 242cbf2d71fSMatthew Dillon while ((path = argv[i]) != NULL || i == 0) { 243cbf2d71fSMatthew Dillon if (path == NULL || strcmp(path, "-") == 0) { 2444b88c807SRodney W. Grimes filename = "stdin"; 2451b00c916SRuslan Ermilov fd = STDIN_FILENO; 246cbf2d71fSMatthew Dillon } else { 247cbf2d71fSMatthew Dillon filename = path; 248aefe30c5SMariusz Zaborski fd = fileargs_open(fa, path); 249cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 250cbf2d71fSMatthew Dillon if (fd < 0 && errno == EOPNOTSUPP) 25143e09ab2SRuslan Ermilov fd = udom_open(path, O_RDONLY); 252cbf2d71fSMatthew Dillon #endif 253cbf2d71fSMatthew Dillon } 254cbf2d71fSMatthew Dillon if (fd < 0) { 255cbf2d71fSMatthew Dillon warn("%s", path); 256001aff9fSBruce Evans rval = 1; 257a33ee411SAlex Richardson #ifndef BOOTSTRAP_CAT 258cbf2d71fSMatthew Dillon } else if (cooked) { 2591b00c916SRuslan Ermilov if (fd == STDIN_FILENO) 2601b00c916SRuslan Ermilov cook_cat(stdin); 2611b00c916SRuslan Ermilov else { 2621b00c916SRuslan Ermilov fp = fdopen(fd, "r"); 263cbf2d71fSMatthew Dillon cook_cat(fp); 264cbf2d71fSMatthew Dillon fclose(fp); 2651b00c916SRuslan Ermilov } 266a33ee411SAlex Richardson #endif 267cbf2d71fSMatthew Dillon } else { 2688113cc82SMartin Matuska #ifndef BOOTSTRAP_CAT 269*c6f9df70SDag-Erling Smørgrav if (in_kernel_copy(fd) != 0) { 2703c773cadSMartin Matuska if (errno == EINVAL || errno == EBADF || 2713c773cadSMartin Matuska errno == EISDIR) 272cbf2d71fSMatthew Dillon raw_cat(fd); 2738113cc82SMartin Matuska else 2748113cc82SMartin Matuska err(1, "stdout"); 2758113cc82SMartin Matuska } 2768113cc82SMartin Matuska #else 2778113cc82SMartin Matuska raw_cat(fd); 2788113cc82SMartin Matuska #endif 2791b00c916SRuslan Ermilov if (fd != STDIN_FILENO) 280cbf2d71fSMatthew Dillon close(fd); 2814b88c807SRodney W. Grimes } 282cbf2d71fSMatthew Dillon if (path == NULL) 283cbf2d71fSMatthew Dillon break; 284cbf2d71fSMatthew Dillon ++i; 2854b88c807SRodney W. Grimes } 2864b88c807SRodney W. Grimes } 2874b88c807SRodney W. Grimes 288a33ee411SAlex Richardson #ifndef BOOTSTRAP_CAT 289cbf2d71fSMatthew Dillon static void 29078a3801dSWarner Losh cook_cat(FILE *fp) 2914b88c807SRodney W. Grimes { 29278a3801dSWarner Losh int ch, gobble, line, prev; 2932aa6b16fSAndrey A. Chernov wint_t wch; 2944b88c807SRodney W. Grimes 2951b00c916SRuslan Ermilov /* Reset EOF condition on stdin. */ 2961b00c916SRuslan Ermilov if (fp == stdin && feof(stdin)) 2971b00c916SRuslan Ermilov clearerr(stdin); 2981b00c916SRuslan Ermilov 2994b88c807SRodney W. Grimes line = gobble = 0; 3004b88c807SRodney W. Grimes for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { 3014b88c807SRodney W. Grimes if (prev == '\n') { 3024b88c807SRodney W. Grimes if (sflag) { 3034b88c807SRodney W. Grimes if (ch == '\n') { 304bf5f0c44STim J. Robbins if (gobble) 305bf5f0c44STim J. Robbins continue; 306bf5f0c44STim J. Robbins gobble = 1; 307bf5f0c44STim J. Robbins } else 308bf5f0c44STim J. Robbins gobble = 0; 309bf5f0c44STim J. Robbins } 3106d2e5f3dSSevan Janiyan if (nflag) { 3116d2e5f3dSSevan Janiyan if (!bflag || ch != '\n') { 312bf5f0c44STim J. Robbins (void)fprintf(stdout, "%6d\t", ++line); 313bf5f0c44STim J. Robbins if (ferror(stdout)) 314bf5f0c44STim J. Robbins break; 3156d2e5f3dSSevan Janiyan } else if (eflag) { 3166d2e5f3dSSevan Janiyan (void)fprintf(stdout, "%6s\t", ""); 3176d2e5f3dSSevan Janiyan if (ferror(stdout)) 3186d2e5f3dSSevan Janiyan break; 3196d2e5f3dSSevan Janiyan } 320bf5f0c44STim J. Robbins } 321bf5f0c44STim J. Robbins } 322bf5f0c44STim J. Robbins if (ch == '\n') { 323bf5f0c44STim J. Robbins if (eflag && putchar('$') == EOF) 3244b88c807SRodney W. Grimes break; 3254b88c807SRodney W. Grimes } else if (ch == '\t') { 3264b88c807SRodney W. Grimes if (tflag) { 3274b88c807SRodney W. Grimes if (putchar('^') == EOF || putchar('I') == EOF) 3284b88c807SRodney W. Grimes break; 3294b88c807SRodney W. Grimes continue; 3304b88c807SRodney W. Grimes } 3314b88c807SRodney W. Grimes } else if (vflag) { 3322aa6b16fSAndrey A. Chernov (void)ungetc(ch, fp); 3332aa6b16fSAndrey A. Chernov /* 3342aa6b16fSAndrey A. Chernov * Our getwc(3) doesn't change file position 3352aa6b16fSAndrey A. Chernov * on error. 3362aa6b16fSAndrey A. Chernov */ 3372aa6b16fSAndrey A. Chernov if ((wch = getwc(fp)) == WEOF) { 3382aa6b16fSAndrey A. Chernov if (ferror(fp) && errno == EILSEQ) { 3392aa6b16fSAndrey A. Chernov clearerr(fp); 3402aa6b16fSAndrey A. Chernov /* Resync attempt. */ 3412aa6b16fSAndrey A. Chernov memset(&fp->_mbstate, 0, sizeof(mbstate_t)); 3422aa6b16fSAndrey A. Chernov if ((ch = getc(fp)) == EOF) 3432aa6b16fSAndrey A. Chernov break; 3442aa6b16fSAndrey A. Chernov wch = ch; 3452aa6b16fSAndrey A. Chernov goto ilseq; 3462aa6b16fSAndrey A. Chernov } else 3472aa6b16fSAndrey A. Chernov break; 3482aa6b16fSAndrey A. Chernov } 3492aa6b16fSAndrey A. Chernov if (!iswascii(wch) && !iswprint(wch)) { 3502aa6b16fSAndrey A. Chernov ilseq: 3514b88c807SRodney W. Grimes if (putchar('M') == EOF || putchar('-') == EOF) 3524b88c807SRodney W. Grimes break; 3532aa6b16fSAndrey A. Chernov wch = toascii(wch); 3544b88c807SRodney W. Grimes } 3552aa6b16fSAndrey A. Chernov if (iswcntrl(wch)) { 3562aa6b16fSAndrey A. Chernov ch = toascii(wch); 3572aa6b16fSAndrey A. Chernov ch = (ch == '\177') ? '?' : (ch | 0100); 3582aa6b16fSAndrey A. Chernov if (putchar('^') == EOF || putchar(ch) == EOF) 3594b88c807SRodney W. Grimes break; 3604b88c807SRodney W. Grimes continue; 3614b88c807SRodney W. Grimes } 3622aa6b16fSAndrey A. Chernov if (putwchar(wch) == WEOF) 3632aa6b16fSAndrey A. Chernov break; 3642aa6b16fSAndrey A. Chernov ch = -1; 3652aa6b16fSAndrey A. Chernov continue; 3664b88c807SRodney W. Grimes } 3674b88c807SRodney W. Grimes if (putchar(ch) == EOF) 3684b88c807SRodney W. Grimes break; 3694b88c807SRodney W. Grimes } 3704b88c807SRodney W. Grimes if (ferror(fp)) { 3714b88c807SRodney W. Grimes warn("%s", filename); 372001aff9fSBruce Evans rval = 1; 3734b88c807SRodney W. Grimes clearerr(fp); 3744b88c807SRodney W. Grimes } 3754b88c807SRodney W. Grimes if (ferror(stdout)) 3764b88c807SRodney W. Grimes err(1, "stdout"); 3774b88c807SRodney W. Grimes } 3788113cc82SMartin Matuska 3798113cc82SMartin Matuska static ssize_t 3808113cc82SMartin Matuska in_kernel_copy(int rfd) 3818113cc82SMartin Matuska { 3828113cc82SMartin Matuska int wfd; 3838113cc82SMartin Matuska ssize_t ret; 3848113cc82SMartin Matuska 3858113cc82SMartin Matuska wfd = fileno(stdout); 3868113cc82SMartin Matuska ret = 1; 3878113cc82SMartin Matuska 3888113cc82SMartin Matuska while (ret > 0) 3898113cc82SMartin Matuska ret = copy_file_range(rfd, NULL, wfd, NULL, SSIZE_MAX, 0); 3908113cc82SMartin Matuska 3918113cc82SMartin Matuska return (ret); 3928113cc82SMartin Matuska } 393a33ee411SAlex Richardson #endif /* BOOTSTRAP_CAT */ 3944b88c807SRodney W. Grimes 395cbf2d71fSMatthew Dillon static void 39678a3801dSWarner Losh raw_cat(int rfd) 3974b88c807SRodney W. Grimes { 398ca23e64eSWarner Losh long pagesize; 39978a3801dSWarner Losh int off, wfd; 400a5da0999SWarner Losh ssize_t nr, nw; 401a5da0999SWarner Losh static size_t bsize; 4029afa09cdSMark Murray static char *buf = NULL; 4034b88c807SRodney W. Grimes struct stat sbuf; 4044b88c807SRodney W. Grimes 4054b88c807SRodney W. Grimes wfd = fileno(stdout); 4064b88c807SRodney W. Grimes if (buf == NULL) { 4074b88c807SRodney W. Grimes if (fstat(wfd, &sbuf)) 408e3481b29SJaakko Heinonen err(1, "stdout"); 409e9cbc9a7SIvan Voras if (S_ISREG(sbuf.st_mode)) { 410e9cbc9a7SIvan Voras /* If there's plenty of RAM, use a large copy buffer */ 411e9cbc9a7SIvan Voras if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD) 412e9cbc9a7SIvan Voras bsize = MIN(BUFSIZE_MAX, MAXPHYS * 8); 413e9cbc9a7SIvan Voras else 414e9cbc9a7SIvan Voras bsize = BUFSIZE_SMALL; 415ca23e64eSWarner Losh } else { 416ca23e64eSWarner Losh bsize = sbuf.st_blksize; 417ca23e64eSWarner Losh pagesize = sysconf(_SC_PAGESIZE); 418ca23e64eSWarner Losh if (pagesize > 0) 419ca23e64eSWarner Losh bsize = MAX(bsize, (size_t)pagesize); 420ca23e64eSWarner Losh } 421d1762d1fSWarner Losh if ((buf = malloc(bsize)) == NULL) 422e9cbc9a7SIvan Voras err(1, "malloc() failure of IO buffer"); 4234b88c807SRodney W. Grimes } 4244b88c807SRodney W. Grimes while ((nr = read(rfd, buf, bsize)) > 0) 4254b88c807SRodney W. Grimes for (off = 0; nr; nr -= nw, off += nw) 426a5da0999SWarner Losh if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) 4274b88c807SRodney W. Grimes err(1, "stdout"); 428001aff9fSBruce Evans if (nr < 0) { 4294b88c807SRodney W. Grimes warn("%s", filename); 430001aff9fSBruce Evans rval = 1; 431001aff9fSBruce Evans } 4324b88c807SRodney W. Grimes } 433cbf2d71fSMatthew Dillon 434cbf2d71fSMatthew Dillon #ifndef NO_UDOM_SUPPORT 435cbf2d71fSMatthew Dillon 436cbf2d71fSMatthew Dillon static int 43778a3801dSWarner Losh udom_open(const char *path, int flags) 438cbf2d71fSMatthew Dillon { 4391c9fbb5aSHiroki Sato struct addrinfo hints, *res, *res0; 4401c9fbb5aSHiroki Sato char rpath[PATH_MAX]; 4410614d739SMariusz Zaborski int error, fd, serrno; 442aefe30c5SMariusz Zaborski cap_rights_t rights; 443cbf2d71fSMatthew Dillon 444cbf2d71fSMatthew Dillon /* 4451c9fbb5aSHiroki Sato * Construct the unix domain socket address and attempt to connect. 446cbf2d71fSMatthew Dillon */ 4471c9fbb5aSHiroki Sato bzero(&hints, sizeof(hints)); 4481c9fbb5aSHiroki Sato hints.ai_family = AF_LOCAL; 449aefe30c5SMariusz Zaborski 450aefe30c5SMariusz Zaborski if (fileargs_realpath(fa, path, rpath) == NULL) 4511c9fbb5aSHiroki Sato return (-1); 452aefe30c5SMariusz Zaborski 453aefe30c5SMariusz Zaborski error = cap_getaddrinfo(capnet, rpath, NULL, &hints, &res0); 4541c9fbb5aSHiroki Sato if (error) { 4551c9fbb5aSHiroki Sato warn("%s", gai_strerror(error)); 4561c9fbb5aSHiroki Sato errno = EINVAL; 45788485b4aSTim J. Robbins return (-1); 45888485b4aSTim J. Robbins } 459aefe30c5SMariusz Zaborski cap_rights_init(&rights, CAP_CONNECT, CAP_READ, CAP_WRITE, 460aefe30c5SMariusz Zaborski CAP_SHUTDOWN, CAP_FSTAT, CAP_FCNTL); 46138f57faaSAlfonso Gregory 46238f57faaSAlfonso Gregory /* Default error if something goes wrong. */ 46338f57faaSAlfonso Gregory serrno = EINVAL; 46438f57faaSAlfonso Gregory 4651c9fbb5aSHiroki Sato for (res = res0; res != NULL; res = res->ai_next) { 4661c9fbb5aSHiroki Sato fd = socket(res->ai_family, res->ai_socktype, 4671c9fbb5aSHiroki Sato res->ai_protocol); 4681c9fbb5aSHiroki Sato if (fd < 0) { 4696e8062c8SMariusz Zaborski serrno = errno; 4701c9fbb5aSHiroki Sato freeaddrinfo(res0); 4716e8062c8SMariusz Zaborski errno = serrno; 4721c9fbb5aSHiroki Sato return (-1); 4731c9fbb5aSHiroki Sato } 474aefe30c5SMariusz Zaborski if (caph_rights_limit(fd, &rights) < 0) { 4756e8062c8SMariusz Zaborski serrno = errno; 476aefe30c5SMariusz Zaborski close(fd); 477c664d8dfSMariusz Zaborski freeaddrinfo(res0); 4786e8062c8SMariusz Zaborski errno = serrno; 479aefe30c5SMariusz Zaborski return (-1); 480aefe30c5SMariusz Zaborski } 481aefe30c5SMariusz Zaborski error = cap_connect(capnet, fd, res->ai_addr, res->ai_addrlen); 4821c9fbb5aSHiroki Sato if (error == 0) 4831c9fbb5aSHiroki Sato break; 4841c9fbb5aSHiroki Sato else { 4856e8062c8SMariusz Zaborski serrno = errno; 486cbf2d71fSMatthew Dillon close(fd); 487cbf2d71fSMatthew Dillon } 488cbf2d71fSMatthew Dillon } 4891c9fbb5aSHiroki Sato freeaddrinfo(res0); 490cbf2d71fSMatthew Dillon 49138f57faaSAlfonso Gregory if (res == NULL) { 49238f57faaSAlfonso Gregory errno = serrno; 49338f57faaSAlfonso Gregory return (-1); 49438f57faaSAlfonso Gregory } 49538f57faaSAlfonso Gregory 496cbf2d71fSMatthew Dillon /* 497cbf2d71fSMatthew Dillon * handle the open flags by shutting down appropriate directions 498cbf2d71fSMatthew Dillon */ 49938f57faaSAlfonso Gregory 500cbf2d71fSMatthew Dillon switch (flags & O_ACCMODE) { 501cbf2d71fSMatthew Dillon case O_RDONLY: 502aefe30c5SMariusz Zaborski cap_rights_clear(&rights, CAP_WRITE); 503*c6f9df70SDag-Erling Smørgrav if (shutdown(fd, SHUT_WR) != 0) 5042c61418dSTim J. Robbins warn(NULL); 505cbf2d71fSMatthew Dillon break; 506cbf2d71fSMatthew Dillon case O_WRONLY: 507aefe30c5SMariusz Zaborski cap_rights_clear(&rights, CAP_READ); 508*c6f9df70SDag-Erling Smørgrav if (shutdown(fd, SHUT_RD) != 0) 5092c61418dSTim J. Robbins warn(NULL); 510cbf2d71fSMatthew Dillon break; 511cbf2d71fSMatthew Dillon default: 512cbf2d71fSMatthew Dillon break; 513cbf2d71fSMatthew Dillon } 514aefe30c5SMariusz Zaborski 515aefe30c5SMariusz Zaborski cap_rights_clear(&rights, CAP_CONNECT, CAP_SHUTDOWN); 516*c6f9df70SDag-Erling Smørgrav if (caph_rights_limit(fd, &rights) != 0) { 5176e8062c8SMariusz Zaborski serrno = errno; 518aefe30c5SMariusz Zaborski close(fd); 5196e8062c8SMariusz Zaborski errno = serrno; 520aefe30c5SMariusz Zaborski return (-1); 521aefe30c5SMariusz Zaborski } 522cbf2d71fSMatthew Dillon return (fd); 523cbf2d71fSMatthew Dillon } 524cbf2d71fSMatthew Dillon 525cbf2d71fSMatthew Dillon #endif 526