Created
November 15, 2015 19:31
-
-
Save RyanBreaker/48a332f10fd3ceab5606 to your computer and use it in GitHub Desktop.
UNIX V5, OpenBSD, Plan 9, FreeBSD, and GNU coreutils implementations of echo.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
main(argc, argv) | |
int argc; | |
char *argv[]; | |
{ | |
int i; | |
argc--; | |
for(i=1; i<=argc; i++) | |
printf("%s%c", argv[i], i==argc? '\n': ' '); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* $OpenBSD: echo.c,v 1.7 2009/10/27 23:59:21 deraadt Exp $ */ | |
/* $NetBSD: echo.c,v 1.6 1995/03/21 09:04:27 cgd Exp $ */ | |
/* | |
* Copyright (c) 1989, 1993 | |
* The Regents of the University of California. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* 3. Neither the name of the University nor the names of its contributors | |
* may be used to endorse or promote products derived from this software | |
* without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
* SUCH DAMAGE. | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
/* ARGSUSED */ | |
int | |
main(int argc, char *argv[]) | |
{ | |
int nflag; | |
/* This utility may NOT do getopt(3) option parsing. */ | |
if (*++argv && !strcmp(*argv, "-n")) { | |
++argv; | |
nflag = 1; | |
} | |
else | |
nflag = 0; | |
while (*argv) { | |
(void)fputs(*argv, stdout); | |
if (*++argv) | |
putchar(' '); | |
} | |
if (!nflag) | |
putchar('\n'); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <u.h> | |
#include <libc.h> | |
void | |
main(int argc, char *argv[]) | |
{ | |
int nflag; | |
int i, len; | |
char *buf, *p; | |
nflag = 0; | |
if(argc > 1 && strcmp(argv[1], "-n") == 0) | |
nflag = 1; | |
len = 1; | |
for(i = 1+nflag; i < argc; i++) | |
len += strlen(argv[i])+1; | |
buf = malloc(len); | |
if(buf == 0) | |
exits("no memory"); | |
p = buf; | |
for(i = 1+nflag; i < argc; i++){ | |
strcpy(p, argv[i]); | |
p += strlen(p); | |
if(i < argc-1) | |
*p++ = ' '; | |
} | |
if(!nflag) | |
*p++ = '\n'; | |
if(write(1, buf, p-buf) < 0){ | |
fprint(2, "echo: write error: %r\n"); | |
exits("write error"); | |
} | |
exits((char *)0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*- | |
* Copyright (c) 1989, 1993 | |
* The Regents of the University of California. All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* 4. Neither the name of the University nor the names of its contributors | |
* may be used to endorse or promote products derived from this software | |
* without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
* SUCH DAMAGE. | |
*/ | |
#if 0 | |
#ifndef lint | |
static char const copyright[] = | |
"@(#) Copyright (c) 1989, 1993\n\ | |
The Regents of the University of California. All rights reserved.\n"; | |
#endif /* not lint */ | |
#ifndef lint | |
static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93"; | |
#endif /* not lint */ | |
#endif | |
#include <sys/cdefs.h> | |
__FBSDID("$FreeBSD$"); | |
#include <sys/types.h> | |
#include <sys/uio.h> | |
#include <assert.h> | |
#include <errno.h> | |
#include <limits.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
/* | |
* Report an error and exit. | |
* Use it instead of err(3) to avoid linking-in stdio. | |
*/ | |
static __dead2 void | |
errexit(const char *prog, const char *reason) | |
{ | |
char *errstr = strerror(errno); | |
write(STDERR_FILENO, prog, strlen(prog)); | |
write(STDERR_FILENO, ": ", 2); | |
write(STDERR_FILENO, reason, strlen(reason)); | |
write(STDERR_FILENO, ": ", 2); | |
write(STDERR_FILENO, errstr, strlen(errstr)); | |
write(STDERR_FILENO, "\n", 1); | |
exit(1); | |
} | |
int | |
main(int argc, char *argv[]) | |
{ | |
int nflag; /* if not set, output a trailing newline. */ | |
int veclen; /* number of writev arguments. */ | |
struct iovec *iov, *vp; /* Elements to write, current element. */ | |
char space[] = " "; | |
char newline[] = "\n"; | |
char *progname = argv[0]; | |
/* This utility may NOT do getopt(3) option parsing. */ | |
if (*++argv && !strcmp(*argv, "-n")) { | |
++argv; | |
--argc; | |
nflag = 1; | |
} else | |
nflag = 0; | |
veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0; | |
if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL) | |
errexit(progname, "malloc"); | |
while (argv[0] != NULL) { | |
size_t len; | |
len = strlen(argv[0]); | |
/* | |
* If the next argument is NULL then this is this | |
* the last argument, therefore we need to check | |
* for a trailing \c. | |
*/ | |
if (argv[1] == NULL) { | |
/* is there room for a '\c' and is there one? */ | |
if (len >= 2 && | |
argv[0][len - 2] == '\\' && | |
argv[0][len - 1] == 'c') { | |
/* chop it and set the no-newline flag. */ | |
len -= 2; | |
nflag = 1; | |
} | |
} | |
vp->iov_base = *argv; | |
vp++->iov_len = len; | |
if (*++argv) { | |
vp->iov_base = space; | |
vp++->iov_len = 1; | |
} | |
} | |
if (!nflag) { | |
veclen++; | |
vp->iov_base = newline; | |
vp++->iov_len = 1; | |
} | |
/* assert(veclen == (vp - iov)); */ | |
while (veclen) { | |
int nwrite; | |
nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen; | |
if (writev(STDOUT_FILENO, iov, nwrite) == -1) | |
errexit(progname, "write"); | |
iov += nwrite; | |
veclen -= nwrite; | |
} | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* echo.c, derived from code echo.c in Bash. | |
Copyright (C) 1987, 1989, 1991-1997, 1999-2005, 2007-2011 Free Software | |
Foundation, Inc. | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
#include <config.h> | |
#include <stdio.h> | |
#include <sys/types.h> | |
#include "system.h" | |
/* The official name of this program (e.g., no `g' prefix). */ | |
#define PROGRAM_NAME "echo" | |
#define AUTHORS \ | |
proper_name ("Brian Fox"), \ | |
proper_name ("Chet Ramey") | |
/* If true, interpret backslash escapes by default. */ | |
#ifndef DEFAULT_ECHO_TO_XPG | |
enum { DEFAULT_ECHO_TO_XPG = false }; | |
#endif | |
void | |
usage (int status) | |
{ | |
if (status != EXIT_SUCCESS) | |
fprintf (stderr, _("Try `%s --help' for more information.\n"), | |
program_name); | |
else | |
{ | |
printf (_("\ | |
Usage: %s [SHORT-OPTION]... [STRING]...\n\ | |
or: %s LONG-OPTION\n\ | |
"), program_name, program_name); | |
fputs (_("\ | |
Echo the STRING(s) to standard output.\n\ | |
\n\ | |
-n do not output the trailing newline\n\ | |
"), stdout); | |
fputs (_(DEFAULT_ECHO_TO_XPG | |
? N_("\ | |
-e enable interpretation of backslash escapes (default)\n\ | |
-E disable interpretation of backslash escapes\n") | |
: N_("\ | |
-e enable interpretation of backslash escapes\n\ | |
-E disable interpretation of backslash escapes (default)\n")), | |
stdout); | |
fputs (HELP_OPTION_DESCRIPTION, stdout); | |
fputs (VERSION_OPTION_DESCRIPTION, stdout); | |
fputs (_("\ | |
\n\ | |
If -e is in effect, the following sequences are recognized:\n\ | |
\n\ | |
"), stdout); | |
fputs (_("\ | |
\\\\ backslash\n\ | |
\\a alert (BEL)\n\ | |
\\b backspace\n\ | |
\\c produce no further output\n\ | |
\\e escape\n\ | |
\\f form feed\n\ | |
\\n new line\n\ | |
\\r carriage return\n\ | |
\\t horizontal tab\n\ | |
\\v vertical tab\n\ | |
"), stdout); | |
fputs (_("\ | |
\\0NNN byte with octal value NNN (1 to 3 digits)\n\ | |
\\xHH byte with hexadecimal value HH (1 to 2 digits)\n\ | |
"), stdout); | |
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME); | |
emit_ancillary_info (); | |
} | |
exit (status); | |
} | |
/* Convert C from hexadecimal character to integer. */ | |
static int | |
hextobin (unsigned char c) | |
{ | |
switch (c) | |
{ | |
default: return c - '0'; | |
case 'a': case 'A': return 10; | |
case 'b': case 'B': return 11; | |
case 'c': case 'C': return 12; | |
case 'd': case 'D': return 13; | |
case 'e': case 'E': return 14; | |
case 'f': case 'F': return 15; | |
} | |
} | |
/* Print the words in LIST to standard output. If the first word is | |
`-n', then don't print a trailing newline. We also support the | |
echo syntax from Version 9 unix systems. */ | |
int | |
main (int argc, char **argv) | |
{ | |
bool display_return = true; | |
bool allow_options = | |
(! getenv ("POSIXLY_CORRECT") | |
|| (! DEFAULT_ECHO_TO_XPG && 1 < argc && STREQ (argv[1], "-n"))); | |
/* System V machines already have a /bin/sh with a v9 behavior. | |
Use the identical behavior for these machines so that the | |
existing system shell scripts won't barf. */ | |
bool do_v9 = DEFAULT_ECHO_TO_XPG; | |
initialize_main (&argc, &argv); | |
set_program_name (argv[0]); | |
setlocale (LC_ALL, ""); | |
bindtextdomain (PACKAGE, LOCALEDIR); | |
textdomain (PACKAGE); | |
atexit (close_stdout); | |
/* We directly parse options, rather than use parse_long_options, in | |
order to avoid accepting abbreviations. */ | |
if (allow_options && argc == 2) | |
{ | |
if (STREQ (argv[1], "--help")) | |
usage (EXIT_SUCCESS); | |
if (STREQ (argv[1], "--version")) | |
{ | |
version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS, | |
(char *) NULL); | |
exit (EXIT_SUCCESS); | |
} | |
} | |
--argc; | |
++argv; | |
if (allow_options) | |
while (argc > 0 && *argv[0] == '-') | |
{ | |
char const *temp = argv[0] + 1; | |
size_t i; | |
/* If it appears that we are handling options, then make sure that | |
all of the options specified are actually valid. Otherwise, the | |
string should just be echoed. */ | |
for (i = 0; temp[i]; i++) | |
switch (temp[i]) | |
{ | |
case 'e': case 'E': case 'n': | |
break; | |
default: | |
goto just_echo; | |
} | |
if (i == 0) | |
goto just_echo; | |
/* All of the options in TEMP are valid options to ECHO. | |
Handle them. */ | |
while (*temp) | |
switch (*temp++) | |
{ | |
case 'e': | |
do_v9 = true; | |
break; | |
case 'E': | |
do_v9 = false; | |
break; | |
case 'n': | |
display_return = false; | |
break; | |
} | |
argc--; | |
argv++; | |
} | |
just_echo: | |
if (do_v9) | |
{ | |
while (argc > 0) | |
{ | |
char const *s = argv[0]; | |
unsigned char c; | |
while ((c = *s++)) | |
{ | |
if (c == '\\' && *s) | |
{ | |
switch (c = *s++) | |
{ | |
case 'a': c = '\a'; break; | |
case 'b': c = '\b'; break; | |
case 'c': exit (EXIT_SUCCESS); | |
case 'e': c = '\x1B'; break; | |
case 'f': c = '\f'; break; | |
case 'n': c = '\n'; break; | |
case 'r': c = '\r'; break; | |
case 't': c = '\t'; break; | |
case 'v': c = '\v'; break; | |
case 'x': | |
{ | |
unsigned char ch = *s; | |
if (! isxdigit (ch)) | |
goto not_an_escape; | |
s++; | |
c = hextobin (ch); | |
ch = *s; | |
if (isxdigit (ch)) | |
{ | |
s++; | |
c = c * 16 + hextobin (ch); | |
} | |
} | |
break; | |
case '0': | |
c = 0; | |
if (! ('0' <= *s && *s <= '7')) | |
break; | |
c = *s++; | |
/* Fall through. */ | |
case '1': case '2': case '3': | |
case '4': case '5': case '6': case '7': | |
c -= '0'; | |
if ('0' <= *s && *s <= '7') | |
c = c * 8 + (*s++ - '0'); | |
if ('0' <= *s && *s <= '7') | |
c = c * 8 + (*s++ - '0'); | |
break; | |
case '\\': break; | |
not_an_escape: | |
default: putchar ('\\'); break; | |
} | |
} | |
putchar (c); | |
} | |
argc--; | |
argv++; | |
if (argc > 0) | |
putchar (' '); | |
} | |
} | |
else | |
{ | |
while (argc > 0) | |
{ | |
fputs (argv[0], stdout); | |
argc--; | |
argv++; | |
if (argc > 0) | |
putchar (' '); | |
} | |
} | |
if (display_return) | |
putchar ('\n'); | |
exit (EXIT_SUCCESS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment