aboutsummaryrefslogtreecommitdiff
path: root/toys/posix/echo.c
blob: 6817ce228529b853726cbae90fa5e9f39fd62631 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* echo.c - echo supporting -n and -e.
 *
 * Copyright 2007 Rob Landley <rob@landley.net>
 *
 * See http://opengroup.org/onlinepubs/9699919799/utilities/echo.html
 *
 * Deviations from posix: we parse command line options, as Linux has
 * consistently done since 1992. Posix defaults -e to on, we require -e.
 * We also honor -- to _stop_ option parsing (bash doesn't, we go with
 * consistency over compatibility here).

USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK|TOYFLAG_LINEBUF))

config ECHO
  bool "echo"
  default y
  help
    usage: echo [-neE] [ARG...]

    Write each argument to stdout, one space between each, followed by a newline.

    -n	No trailing newline
    -E	Print escape sequences literally (default)
    -e	Process the following escape sequences:
    	\\  Backslash		\0NNN Octal (1-3 digit)	\xHH Hex (1-2 digit)
    	\a  Alert (beep/flash)	\b  Backspace		\c  Stop here (no \n)
    	\f  Form feed		\n  Newline		\r  Carriage return
    	\t  Horizontal tab	\v  Vertical tab
*/

#define FOR_echo
#include "toys.h"

void echo_main(void)
{
  int i = 0;
  char *arg, *c, out[8];

  while ((arg = toys.optargs[i])) {
    if (i++) putchar(' ');

    // Should we output arg verbatim?

    if (!FLAG(e)) {
      xprintf("%s", arg);
      continue;
    }

    // Handle -e

    for (c = arg; *c; ) {
      unsigned u;

      if (*c == '\\' && c[1] == 'c') return;
      if ((u = unescape2(&c, 1))<128) putchar(u);
      else printf("%.*s", (int)wcrtomb(out, u, 0), out);
    }
  }

  // Output "\n" if no -n
  if (!FLAG(n)) putchar('\n');
}