19ddb49cbSWarner Losh /*- 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 * Redistribution and use in source and binary forms, with or without 64b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 74b88c807SRodney W. Grimes * are met: 84b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 94b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 104b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 114b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 124b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 134b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 144b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 154b88c807SRodney W. Grimes * without specific prior written permission. 164b88c807SRodney W. Grimes * 174b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 184b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 194b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 204b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 214b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 224b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 234b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 244b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 254b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 264b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 274b88c807SRodney W. Grimes * SUCH DAMAGE. 284b88c807SRodney W. Grimes */ 294b88c807SRodney W. Grimes 3009a80d48SDavid E. O'Brien #if 0 314b88c807SRodney W. Grimes #ifndef lint 3278b09ffeSSteve Price static char const copyright[] = 334b88c807SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\ 344b88c807SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 354b88c807SRodney W. Grimes #endif /* not lint */ 364b88c807SRodney W. Grimes 374b88c807SRodney W. Grimes #ifndef lint 3895d0bf65SPhilippe Charnier static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93"; 394b88c807SRodney W. Grimes #endif /* not lint */ 4009a80d48SDavid E. O'Brien #endif 415eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 425eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 434b88c807SRodney W. Grimes 4491b7d6dcSDiomidis Spinellis #include <sys/types.h> 4591b7d6dcSDiomidis Spinellis #include <sys/uio.h> 464b88c807SRodney W. Grimes 4791b7d6dcSDiomidis Spinellis #include <assert.h> 4891b7d6dcSDiomidis Spinellis #include <errno.h> 4991b7d6dcSDiomidis Spinellis #include <limits.h> 5091b7d6dcSDiomidis Spinellis #include <stdlib.h> 5191b7d6dcSDiomidis Spinellis #include <string.h> 5291b7d6dcSDiomidis Spinellis #include <unistd.h> 5391b7d6dcSDiomidis Spinellis 5491b7d6dcSDiomidis Spinellis /* 5591b7d6dcSDiomidis Spinellis * Report an error and exit. 5691b7d6dcSDiomidis Spinellis * Use it instead of err(3) to avoid linking-in stdio. 5791b7d6dcSDiomidis Spinellis */ 5891b7d6dcSDiomidis Spinellis static void 5991b7d6dcSDiomidis Spinellis errexit(const char *prog, const char *reason) 6091b7d6dcSDiomidis Spinellis { 6191b7d6dcSDiomidis Spinellis char *errstr = strerror(errno); 6291b7d6dcSDiomidis Spinellis write(STDERR_FILENO, prog, strlen(prog)); 6391b7d6dcSDiomidis Spinellis write(STDERR_FILENO, ": ", 2); 6491b7d6dcSDiomidis Spinellis write(STDERR_FILENO, reason, strlen(reason)); 6591b7d6dcSDiomidis Spinellis write(STDERR_FILENO, ": ", 2); 6691b7d6dcSDiomidis Spinellis write(STDERR_FILENO, errstr, strlen(errstr)); 6791b7d6dcSDiomidis Spinellis write(STDERR_FILENO, "\n", 1); 6891b7d6dcSDiomidis Spinellis exit(1); 6991b7d6dcSDiomidis Spinellis } 7091b7d6dcSDiomidis Spinellis 714b88c807SRodney W. Grimes int 7291b7d6dcSDiomidis Spinellis main(int argc, char *argv[]) 734b88c807SRodney W. Grimes { 746188858aSAlfred Perlstein int nflag; /* if not set, output a trailing newline. */ 7591b7d6dcSDiomidis Spinellis int veclen; /* number of writev arguments. */ 7691b7d6dcSDiomidis Spinellis struct iovec *iov, *vp; /* Elements to write, current element. */ 7791b7d6dcSDiomidis Spinellis char space[] = " "; 7891b7d6dcSDiomidis Spinellis char newline[] = "\n"; 7991b7d6dcSDiomidis Spinellis char *progname = argv[0]; 804b88c807SRodney W. Grimes 814b88c807SRodney W. Grimes /* This utility may NOT do getopt(3) option parsing. */ 824b88c807SRodney W. Grimes if (*++argv && !strcmp(*argv, "-n")) { 834b88c807SRodney W. Grimes ++argv; 8491b7d6dcSDiomidis Spinellis --argc; 854b88c807SRodney W. Grimes nflag = 1; 8691b7d6dcSDiomidis Spinellis } else 874b88c807SRodney W. Grimes nflag = 0; 884b88c807SRodney W. Grimes 8991b7d6dcSDiomidis Spinellis veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0; 9091b7d6dcSDiomidis Spinellis 9191b7d6dcSDiomidis Spinellis if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) 9291b7d6dcSDiomidis Spinellis errexit(progname, "malloc"); 9391b7d6dcSDiomidis Spinellis 946188858aSAlfred Perlstein while (argv[0] != NULL) { 95ef3e71daSNate Lawson size_t len; 96ef3e71daSNate Lawson 97ef3e71daSNate Lawson len = strlen(argv[0]); 986cef43a7SJordan K. Hubbard 996188858aSAlfred Perlstein /* 1006188858aSAlfred Perlstein * If the next argument is NULL then this is this 1016188858aSAlfred Perlstein * the last argument, therefore we need to check 1026188858aSAlfred Perlstein * for a trailing \c. 1036188858aSAlfred Perlstein */ 1046188858aSAlfred Perlstein if (argv[1] == NULL) { 1056188858aSAlfred Perlstein /* is there room for a '\c' and is there one? */ 1066188858aSAlfred Perlstein if (len >= 2 && 1076188858aSAlfred Perlstein argv[0][len - 2] == '\\' && 1086188858aSAlfred Perlstein argv[0][len - 1] == 'c') { 1096188858aSAlfred Perlstein /* chop it and set the no-newline flag. */ 110ef3e71daSNate Lawson len -= 2; 1116cef43a7SJordan K. Hubbard nflag = 1; 1126cef43a7SJordan K. Hubbard } 1136188858aSAlfred Perlstein } 11491b7d6dcSDiomidis Spinellis vp->iov_base = *argv; 11591b7d6dcSDiomidis Spinellis vp++->iov_len = len; 11691b7d6dcSDiomidis Spinellis if (*++argv) { 11791b7d6dcSDiomidis Spinellis vp->iov_base = space; 11891b7d6dcSDiomidis Spinellis vp++->iov_len = 1; 1194b88c807SRodney W. Grimes } 12091b7d6dcSDiomidis Spinellis } 12191b7d6dcSDiomidis Spinellis if (!nflag) { 12291b7d6dcSDiomidis Spinellis veclen++; 12391b7d6dcSDiomidis Spinellis vp->iov_base = newline; 12491b7d6dcSDiomidis Spinellis vp++->iov_len = 1; 12591b7d6dcSDiomidis Spinellis } 12691b7d6dcSDiomidis Spinellis /* assert(veclen == (vp - iov)); */ 12791b7d6dcSDiomidis Spinellis while (veclen) { 12891b7d6dcSDiomidis Spinellis int nwrite; 12991b7d6dcSDiomidis Spinellis 13091b7d6dcSDiomidis Spinellis nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen; 13191b7d6dcSDiomidis Spinellis if (writev(STDOUT_FILENO, iov, nwrite) == -1) 13291b7d6dcSDiomidis Spinellis errexit(progname, "write"); 13391b7d6dcSDiomidis Spinellis iov += nwrite; 13491b7d6dcSDiomidis Spinellis veclen -= nwrite; 13591b7d6dcSDiomidis Spinellis } 1369b2010a2SMark Murray return 0; 1374b88c807SRodney W. Grimes } 138