• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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