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 * Redistribution and use in source and binary forms, with or without 84b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 94b88c807SRodney W. Grimes * are met: 104b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 114b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 124b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 134b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 144b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 164b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 174b88c807SRodney W. Grimes * without specific prior written permission. 184b88c807SRodney W. Grimes * 194b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 204b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 214b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 224b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 234b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 244b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 254b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 264b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 274b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 284b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 294b88c807SRodney W. Grimes * SUCH DAMAGE. 304b88c807SRodney W. Grimes */ 314b88c807SRodney W. Grimes 3209a80d48SDavid E. O'Brien #if 0 334b88c807SRodney W. Grimes #ifndef lint 3478b09ffeSSteve Price static char const copyright[] = 354b88c807SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 364b88c807SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 374b88c807SRodney W. Grimes #endif /* not lint */ 384b88c807SRodney W. Grimes 394b88c807SRodney W. Grimes #ifndef lint 4095d0bf65SPhilippe Charnier static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93"; 414b88c807SRodney W. Grimes #endif /* not lint */ 4209a80d48SDavid E. O'Brien #endif 435eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 445eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 454b88c807SRodney W. Grimes 4691b7d6dcSDiomidis Spinellis #include <sys/types.h> 4791b7d6dcSDiomidis Spinellis #include <sys/uio.h> 484b88c807SRodney W. Grimes 4991b7d6dcSDiomidis Spinellis #include <assert.h> 50cd1693d3SConrad Meyer #include <capsicum_helpers.h> 51cd1693d3SConrad Meyer #include <err.h> 5291b7d6dcSDiomidis Spinellis #include <errno.h> 5391b7d6dcSDiomidis Spinellis #include <limits.h> 5491b7d6dcSDiomidis Spinellis #include <stdlib.h> 5591b7d6dcSDiomidis Spinellis #include <string.h> 5691b7d6dcSDiomidis Spinellis #include <unistd.h> 5791b7d6dcSDiomidis Spinellis 5891b7d6dcSDiomidis Spinellis /* 5991b7d6dcSDiomidis Spinellis * Report an error and exit. 6091b7d6dcSDiomidis Spinellis * Use it instead of err(3) to avoid linking-in stdio. 6191b7d6dcSDiomidis Spinellis */ 62f9bcf9caSColin Percival static __dead2 void 6391b7d6dcSDiomidis Spinellis errexit(const char *prog, const char *reason) 6491b7d6dcSDiomidis Spinellis { 6591b7d6dcSDiomidis Spinellis char *errstr = strerror(errno); 6691b7d6dcSDiomidis Spinellis write(STDERR_FILENO, prog, strlen(prog)); 6791b7d6dcSDiomidis Spinellis write(STDERR_FILENO, ": ", 2); 6891b7d6dcSDiomidis Spinellis write(STDERR_FILENO, reason, strlen(reason)); 6991b7d6dcSDiomidis Spinellis write(STDERR_FILENO, ": ", 2); 7091b7d6dcSDiomidis Spinellis write(STDERR_FILENO, errstr, strlen(errstr)); 7191b7d6dcSDiomidis Spinellis write(STDERR_FILENO, "\n", 1); 7291b7d6dcSDiomidis Spinellis exit(1); 7391b7d6dcSDiomidis Spinellis } 7491b7d6dcSDiomidis Spinellis 754b88c807SRodney W. Grimes int 7691b7d6dcSDiomidis Spinellis main(int argc, char *argv[]) 774b88c807SRodney W. Grimes { 786188858aSAlfred Perlstein int nflag; /* if not set, output a trailing newline. */ 7991b7d6dcSDiomidis Spinellis int veclen; /* number of writev arguments. */ 8091b7d6dcSDiomidis Spinellis struct iovec *iov, *vp; /* Elements to write, current element. */ 8191b7d6dcSDiomidis Spinellis char space[] = " "; 8291b7d6dcSDiomidis Spinellis char newline[] = "\n"; 8391b7d6dcSDiomidis Spinellis char *progname = argv[0]; 844b88c807SRodney W. Grimes 857672a014SMariusz Zaborski if (caph_limit_stdio() < 0 || caph_enter() < 0) 86cd1693d3SConrad Meyer err(1, "capsicum"); 87cd1693d3SConrad Meyer 884b88c807SRodney W. Grimes /* This utility may NOT do getopt(3) option parsing. */ 894b88c807SRodney W. Grimes if (*++argv && !strcmp(*argv, "-n")) { 904b88c807SRodney W. Grimes ++argv; 9191b7d6dcSDiomidis Spinellis --argc; 924b88c807SRodney W. Grimes nflag = 1; 9391b7d6dcSDiomidis Spinellis } else 944b88c807SRodney W. Grimes nflag = 0; 954b88c807SRodney W. Grimes 9691b7d6dcSDiomidis Spinellis veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0; 9791b7d6dcSDiomidis Spinellis 9891b7d6dcSDiomidis Spinellis if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) 9991b7d6dcSDiomidis Spinellis errexit(progname, "malloc"); 10091b7d6dcSDiomidis Spinellis 1016188858aSAlfred Perlstein while (argv[0] != NULL) { 102ef3e71daSNate Lawson size_t len; 103ef3e71daSNate Lawson 104ef3e71daSNate Lawson len = strlen(argv[0]); 1056cef43a7SJordan K. Hubbard 1066188858aSAlfred Perlstein /* 107*a249b285SLi-Wen Hsu * If the next argument is NULL then this is the last argument, 108*a249b285SLi-Wen Hsu * therefore we need to check for a trailing \c. 1096188858aSAlfred Perlstein */ 1106188858aSAlfred Perlstein if (argv[1] == NULL) { 1116188858aSAlfred Perlstein /* is there room for a '\c' and is there one? */ 1126188858aSAlfred Perlstein if (len >= 2 && 1136188858aSAlfred Perlstein argv[0][len - 2] == '\\' && 1146188858aSAlfred Perlstein argv[0][len - 1] == 'c') { 1156188858aSAlfred Perlstein /* chop it and set the no-newline flag. */ 116ef3e71daSNate Lawson len -= 2; 1176cef43a7SJordan K. Hubbard nflag = 1; 1186cef43a7SJordan K. Hubbard } 1196188858aSAlfred Perlstein } 12091b7d6dcSDiomidis Spinellis vp->iov_base = *argv; 12191b7d6dcSDiomidis Spinellis vp++->iov_len = len; 12291b7d6dcSDiomidis Spinellis if (*++argv) { 12391b7d6dcSDiomidis Spinellis vp->iov_base = space; 12491b7d6dcSDiomidis Spinellis vp++->iov_len = 1; 1254b88c807SRodney W. Grimes } 12691b7d6dcSDiomidis Spinellis } 12791b7d6dcSDiomidis Spinellis if (!nflag) { 12891b7d6dcSDiomidis Spinellis veclen++; 12991b7d6dcSDiomidis Spinellis vp->iov_base = newline; 13091b7d6dcSDiomidis Spinellis vp++->iov_len = 1; 13191b7d6dcSDiomidis Spinellis } 13291b7d6dcSDiomidis Spinellis /* assert(veclen == (vp - iov)); */ 13391b7d6dcSDiomidis Spinellis while (veclen) { 13491b7d6dcSDiomidis Spinellis int nwrite; 13591b7d6dcSDiomidis Spinellis 13691b7d6dcSDiomidis Spinellis nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen; 13791b7d6dcSDiomidis Spinellis if (writev(STDOUT_FILENO, iov, nwrite) == -1) 13891b7d6dcSDiomidis Spinellis errexit(progname, "write"); 13991b7d6dcSDiomidis Spinellis iov += nwrite; 14091b7d6dcSDiomidis Spinellis veclen -= nwrite; 14191b7d6dcSDiomidis Spinellis } 1429b2010a2SMark Murray return 0; 1434b88c807SRodney W. Grimes } 144