1 /* echo.c - echo supporting -n and -e.
2 *
3 * Copyright 2007 Rob Landley <rob@landley.net>
4 *
5 * See http://opengroup.org/onlinepubs/9699919799/utilities/echo.html
6 *
7 * Deviations from posix: we parse command line options, as Linux has
8 * consistently done since 1992. Posix defaults -e to on, we require -e.
9 * We also honor -- to _stop_ option parsing (bash doesn't, we go with
10 * consistency over compatibility here).
11
12 USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK))
13
14 config ECHO
15 bool "echo"
16 default y
17 help
18 usage: echo [-neE] [args...]
19
20 Write each argument to stdout, with one space between each, followed
21 by a newline.
22
23 -n No trailing newline
24 -E Print escape sequences literally (default)
25 -e Process the following escape sequences:
26 \\ Backslash
27 \a Alert (beep/flash)
28 \b Backspace
29 \c Stop output here (avoids trailing newline)
30 \f Form feed
31 \n Newline
32 \r Carriage return
33 \t Horizontal tab
34 \v Vertical tab
35 */
36
37 #define FOR_echo
38 #include "toys.h"
39
echo_main(void)40 void echo_main(void)
41 {
42 int i = 0, out;
43 char *arg, *c;
44
45 for (;;) {
46 arg = toys.optargs[i];
47 if (!arg) break;
48 if (i++) putchar(' ');
49
50 // Should we output arg verbatim?
51
52 if (!FLAG(e)) {
53 xprintf("%s", arg);
54 continue;
55 }
56
57 // Handle -e
58
59 for (c = arg;;) {
60 if (!(out = *(c++))) break;
61
62 // handle \escapes
63 if (out == '\\' && *c) {
64 int slash = *(c++), n = unescape(slash);
65
66 if (n) out = n;
67 else if (slash=='c') return;
68 else if (slash=='0') {
69 out = 0;
70 while (*c>='0' && *c<='7' && n++<3) out = (out*8)+*(c++)-'0';
71 } else if (slash=='x') {
72 out = 0;
73 while (n++<2) {
74 if (*c>='0' && *c<='9') out = (out*16)+*(c++)-'0';
75 else {
76 int temp = tolower(*c);
77 if (temp>='a' && temp<='f') {
78 out = (out*16)+temp-'a'+10;
79 c++;
80 } else {
81 if (n==1) {
82 --c;
83 out = '\\';
84 }
85 break;
86 }
87 }
88 }
89 // Slash in front of unknown character, print literal.
90 } else c--;
91 }
92 putchar(out);
93 }
94 }
95
96 // Output "\n" if no -n
97 if (!FLAG(n)) putchar('\n');
98 }
99