PageRenderTime 36ms CodeModel.GetById 13ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/bin/echo/echo.c

https://bitbucket.org/freebsd/freebsd-head/
C | 137 lines | 83 code | 13 blank | 41 comment | 16 complexity | 58d6242ad5cece48fb1a98ec36b13801 MD5 | raw file
  1/*-
  2 * Copyright (c) 1989, 1993
  3 *	The Regents of the University of California.  All rights reserved.
  4 *
  5 * Redistribution and use in source and binary forms, with or without
  6 * modification, are permitted provided that the following conditions
  7 * are met:
  8 * 1. Redistributions of source code must retain the above copyright
  9 *    notice, this list of conditions and the following disclaimer.
 10 * 2. Redistributions in binary form must reproduce the above copyright
 11 *    notice, this list of conditions and the following disclaimer in the
 12 *    documentation and/or other materials provided with the distribution.
 13 * 4. Neither the name of the University nor the names of its contributors
 14 *    may be used to endorse or promote products derived from this software
 15 *    without specific prior written permission.
 16 *
 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 27 * SUCH DAMAGE.
 28 */
 29
 30#if 0
 31#ifndef lint
 32static char const copyright[] =
 33"@(#) Copyright (c) 1989, 1993\n\
 34	The Regents of the University of California.  All rights reserved.\n";
 35#endif /* not lint */
 36
 37#ifndef lint
 38static char sccsid[] = "@(#)echo.c	8.1 (Berkeley) 5/31/93";
 39#endif /* not lint */
 40#endif
 41#include <sys/cdefs.h>
 42__FBSDID("$FreeBSD$");
 43
 44#include <sys/types.h>
 45#include <sys/uio.h>
 46
 47#include <assert.h>
 48#include <errno.h>
 49#include <limits.h>
 50#include <stdlib.h>
 51#include <string.h>
 52#include <unistd.h>
 53
 54/*
 55 * Report an error and exit.
 56 * Use it instead of err(3) to avoid linking-in stdio.
 57 */
 58static __dead2 void
 59errexit(const char *prog, const char *reason)
 60{
 61	char *errstr = strerror(errno);
 62	write(STDERR_FILENO, prog, strlen(prog));
 63	write(STDERR_FILENO, ": ", 2);
 64	write(STDERR_FILENO, reason, strlen(reason));
 65	write(STDERR_FILENO, ": ", 2);
 66	write(STDERR_FILENO, errstr, strlen(errstr));
 67	write(STDERR_FILENO, "\n", 1);
 68	exit(1);
 69}
 70	
 71int
 72main(int argc, char *argv[])
 73{
 74	int nflag;	/* if not set, output a trailing newline. */
 75	int veclen;	/* number of writev arguments. */
 76	struct iovec *iov, *vp; /* Elements to write, current element. */
 77	char space[] = " ";
 78	char newline[] = "\n";
 79	char *progname = argv[0];
 80
 81	/* This utility may NOT do getopt(3) option parsing. */
 82	if (*++argv && !strcmp(*argv, "-n")) {
 83		++argv;
 84		--argc;
 85		nflag = 1;
 86	} else
 87		nflag = 0;
 88
 89	veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;
 90
 91	if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL)
 92		errexit(progname, "malloc");
 93
 94	while (argv[0] != NULL) {
 95		size_t len;
 96		
 97		len = strlen(argv[0]);
 98
 99		/*
100		 * If the next argument is NULL then this is this
101		 * the last argument, therefore we need to check
102		 * for a trailing \c.
103		 */
104		if (argv[1] == NULL) {
105			/* is there room for a '\c' and is there one? */
106			if (len >= 2 &&
107			    argv[0][len - 2] == '\\' &&
108			    argv[0][len - 1] == 'c') {
109				/* chop it and set the no-newline flag. */
110				len -= 2;
111				nflag = 1;
112			}
113		}
114		vp->iov_base = *argv;
115		vp++->iov_len = len;
116		if (*++argv) {
117			vp->iov_base = space;
118			vp++->iov_len = 1;
119		}
120	}
121	if (!nflag) {
122		veclen++;
123		vp->iov_base = newline;
124		vp++->iov_len = 1;
125	}
126	/* assert(veclen == (vp - iov)); */
127	while (veclen) {
128		int nwrite;
129
130		nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;
131		if (writev(STDOUT_FILENO, iov, nwrite) == -1)
132			errexit(progname, "write");
133		iov += nwrite;
134		veclen -= nwrite;
135	}
136	return 0;
137}