1139969Simp/*- 21556Srgrimes * Copyright (c) 1989, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * Redistribution and use in source and binary forms, with or without 61556Srgrimes * modification, are permitted provided that the following conditions 71556Srgrimes * are met: 81556Srgrimes * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 4. Neither the name of the University nor the names of its contributors 141556Srgrimes * may be used to endorse or promote products derived from this software 151556Srgrimes * without specific prior written permission. 161556Srgrimes * 171556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271556Srgrimes * SUCH DAMAGE. 281556Srgrimes */ 291556Srgrimes 30114433Sobrien#if 0 311556Srgrimes#ifndef lint 3220420Sstevestatic char const copyright[] = 331556Srgrimes"@(#) Copyright (c) 1989, 1993\n\ 341556Srgrimes The Regents of the University of California. All rights reserved.\n"; 351556Srgrimes#endif /* not lint */ 361556Srgrimes 371556Srgrimes#ifndef lint 3836009Scharnierstatic char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93"; 39114433Sobrien#endif /* not lint */ 4036009Scharnier#endif 4199109Sobrien#include <sys/cdefs.h> 4299109Sobrien__FBSDID("$FreeBSD$"); 431556Srgrimes 44121010Sdds#include <sys/types.h> 45121010Sdds#include <sys/uio.h> 46121010Sdds 47121010Sdds#include <assert.h> 48121010Sdds#include <errno.h> 49121010Sdds#include <limits.h> 50121010Sdds#include <stdlib.h> 51121010Sdds#include <string.h> 52106835Snjl#include <unistd.h> 531556Srgrimes 54121010Sdds/* 55121010Sdds * Report an error and exit. 56121010Sdds * Use it instead of err(3) to avoid linking-in stdio. 57121010Sdds */ 58181269Scpercivastatic __dead2 void 59121010Sddserrexit(const char *prog, const char *reason) 60121010Sdds{ 61121010Sdds char *errstr = strerror(errno); 62121010Sdds write(STDERR_FILENO, prog, strlen(prog)); 63121010Sdds write(STDERR_FILENO, ": ", 2); 64121010Sdds write(STDERR_FILENO, reason, strlen(reason)); 65121010Sdds write(STDERR_FILENO, ": ", 2); 66121010Sdds write(STDERR_FILENO, errstr, strlen(errstr)); 67121010Sdds write(STDERR_FILENO, "\n", 1); 68121010Sdds exit(1); 69121010Sdds} 70121010Sdds 711556Srgrimesint 72121010Sddsmain(int argc, char *argv[]) 731556Srgrimes{ 7491614Salfred int nflag; /* if not set, output a trailing newline. */ 75121010Sdds int veclen; /* number of writev arguments. */ 76121010Sdds struct iovec *iov, *vp; /* Elements to write, current element. */ 77121010Sdds char space[] = " "; 78121010Sdds char newline[] = "\n"; 79121010Sdds char *progname = argv[0]; 801556Srgrimes 811556Srgrimes /* This utility may NOT do getopt(3) option parsing. */ 821556Srgrimes if (*++argv && !strcmp(*argv, "-n")) { 831556Srgrimes ++argv; 84121010Sdds --argc; 851556Srgrimes nflag = 1; 86121010Sdds } else 871556Srgrimes nflag = 0; 881556Srgrimes 89121010Sdds veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0; 90121010Sdds 91121010Sdds if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) 92121010Sdds errexit(progname, "malloc"); 93121010Sdds 9491614Salfred while (argv[0] != NULL) { 95106835Snjl size_t len; 96106835Snjl 97106835Snjl len = strlen(argv[0]); 9810498Sjkh 9991614Salfred /* 10091614Salfred * If the next argument is NULL then this is this 10191614Salfred * the last argument, therefore we need to check 10291614Salfred * for a trailing \c. 10391614Salfred */ 10491614Salfred if (argv[1] == NULL) { 10591614Salfred /* is there room for a '\c' and is there one? */ 10691614Salfred if (len >= 2 && 10791614Salfred argv[0][len - 2] == '\\' && 10891614Salfred argv[0][len - 1] == 'c') { 10991614Salfred /* chop it and set the no-newline flag. */ 110106835Snjl len -= 2; 11191614Salfred nflag = 1; 11291614Salfred } 11310498Sjkh } 114121010Sdds vp->iov_base = *argv; 115121010Sdds vp++->iov_len = len; 116121010Sdds if (*++argv) { 117121010Sdds vp->iov_base = space; 118121010Sdds vp++->iov_len = 1; 119121010Sdds } 1201556Srgrimes } 121121010Sdds if (!nflag) { 122121010Sdds veclen++; 123121010Sdds vp->iov_base = newline; 124121010Sdds vp++->iov_len = 1; 125121010Sdds } 126121010Sdds /* assert(veclen == (vp - iov)); */ 127121010Sdds while (veclen) { 128121010Sdds int nwrite; 129121010Sdds 130121010Sdds nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen; 131121010Sdds if (writev(STDOUT_FILENO, iov, nwrite) == -1) 132121010Sdds errexit(progname, "write"); 133121010Sdds iov += nwrite; 134121010Sdds veclen -= nwrite; 135121010Sdds } 13691082Smarkm return 0; 1371556Srgrimes} 138