/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. #if 0
  30. #ifndef lint
  31. static char const copyright[] =
  32. "@(#) Copyright (c) 1989, 1993\n\
  33. The Regents of the University of California. All rights reserved.\n";
  34. #endif /* not lint */
  35. #ifndef lint
  36. static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93";
  37. #endif /* not lint */
  38. #endif
  39. #include <sys/cdefs.h>
  40. __FBSDID("$FreeBSD$");
  41. #include <sys/types.h>
  42. #include <sys/uio.h>
  43. #include <assert.h>
  44. #include <errno.h>
  45. #include <limits.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #include <unistd.h>
  49. /*
  50. * Report an error and exit.
  51. * Use it instead of err(3) to avoid linking-in stdio.
  52. */
  53. static __dead2 void
  54. errexit(const char *prog, const char *reason)
  55. {
  56. char *errstr = strerror(errno);
  57. write(STDERR_FILENO, prog, strlen(prog));
  58. write(STDERR_FILENO, ": ", 2);
  59. write(STDERR_FILENO, reason, strlen(reason));
  60. write(STDERR_FILENO, ": ", 2);
  61. write(STDERR_FILENO, errstr, strlen(errstr));
  62. write(STDERR_FILENO, "\n", 1);
  63. exit(1);
  64. }
  65. int
  66. main(int argc, char *argv[])
  67. {
  68. int nflag; /* if not set, output a trailing newline. */
  69. int veclen; /* number of writev arguments. */
  70. struct iovec *iov, *vp; /* Elements to write, current element. */
  71. char space[] = " ";
  72. char newline[] = "\n";
  73. char *progname = argv[0];
  74. /* This utility may NOT do getopt(3) option parsing. */
  75. if (*++argv && !strcmp(*argv, "-n")) {
  76. ++argv;
  77. --argc;
  78. nflag = 1;
  79. } else
  80. nflag = 0;
  81. veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;
  82. if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL)
  83. errexit(progname, "malloc");
  84. while (argv[0] != NULL) {
  85. size_t len;
  86. len = strlen(argv[0]);
  87. /*
  88. * If the next argument is NULL then this is this
  89. * the last argument, therefore we need to check
  90. * for a trailing \c.
  91. */
  92. if (argv[1] == NULL) {
  93. /* is there room for a '\c' and is there one? */
  94. if (len >= 2 &&
  95. argv[0][len - 2] == '\\' &&
  96. argv[0][len - 1] == 'c') {
  97. /* chop it and set the no-newline flag. */
  98. len -= 2;
  99. nflag = 1;
  100. }
  101. }
  102. vp->iov_base = *argv;
  103. vp++->iov_len = len;
  104. if (*++argv) {
  105. vp->iov_base = space;
  106. vp++->iov_len = 1;
  107. }
  108. }
  109. if (!nflag) {
  110. veclen++;
  111. vp->iov_base = newline;
  112. vp++->iov_len = 1;
  113. }
  114. /* assert(veclen == (vp - iov)); */
  115. while (veclen) {
  116. int nwrite;
  117. nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;
  118. if (writev(STDOUT_FILENO, iov, nwrite) == -1)
  119. errexit(progname, "write");
  120. iov += nwrite;
  121. veclen -= nwrite;
  122. }
  123. return 0;
  124. }