diff options
Diffstat (limited to 'coreutils/echo.c')
-rw-r--r-- | coreutils/echo.c | 133 |
1 files changed, 73 insertions, 60 deletions
diff --git a/coreutils/echo.c b/coreutils/echo.c index 31c031528..b600a1fbd 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c | |||
@@ -22,94 +22,107 @@ | |||
22 | * Original copyright notice is retained at the end of this file. | 22 | * Original copyright notice is retained at the end of this file. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | /* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */ | ||
26 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */ | ||
27 | |||
28 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) | ||
29 | * | ||
30 | * Because of behavioral differences, implemented configureable SUSv3 | ||
31 | * or 'fancy' gnu-ish behaviors. Also, reduced size and fixed bugs. | ||
32 | * 1) In handling '\c' escape, the previous version only suppressed the | ||
33 | * trailing newline. SUSv3 specifies _no_ output after '\c'. | ||
34 | * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}. | ||
35 | * The previous version version did not allow 4-digit octals. | ||
36 | */ | ||
37 | |||
25 | #include <stdio.h> | 38 | #include <stdio.h> |
26 | #include <string.h> | 39 | #include <string.h> |
27 | #include <stdlib.h> | 40 | #include <stdlib.h> |
28 | #include "busybox.h" | 41 | #include "busybox.h" |
29 | 42 | ||
30 | extern int | 43 | extern int echo_main(int argc, char** argv) |
31 | echo_main(int argc, char** argv) | ||
32 | { | 44 | { |
33 | int nflag = 0; | 45 | #ifndef CONFIG_FEATURE_FANCY_ECHO |
46 | #define eflag '\\' | ||
47 | ++argv; | ||
48 | #else | ||
49 | const char *p; | ||
50 | int nflag = 1; | ||
34 | int eflag = 0; | 51 | int eflag = 0; |
35 | 52 | ||
36 | /* Skip argv[0]. */ | 53 | while (*++argv && (**argv == '-')) { |
37 | argc--; | 54 | /* If it appears that we are handling options, then make sure |
38 | argv++; | ||
39 | |||
40 | while (argc > 0 && *argv[0] == '-') | ||
41 | { | ||
42 | register char *temp; | ||
43 | register int ix; | ||
44 | |||
45 | /* | ||
46 | * If it appears that we are handling options, then make sure | ||
47 | * that all of the options specified are actually valid. | 55 | * that all of the options specified are actually valid. |
48 | * Otherwise, the string should just be echoed. | 56 | * Otherwise, the string should just be echoed. |
49 | */ | 57 | */ |
50 | temp = argv[0] + 1; | 58 | |
51 | 59 | if (!*(p = *argv + 1)) { /* A single '-', so echo it. */ | |
52 | for (ix = 0; temp[ix]; ix++) | ||
53 | { | ||
54 | if (strrchr("neE", temp[ix]) == 0) | ||
55 | goto just_echo; | ||
56 | } | ||
57 | |||
58 | if (!*temp) | ||
59 | goto just_echo; | 60 | goto just_echo; |
61 | } | ||
60 | 62 | ||
61 | /* | 63 | do { |
62 | * All of the options in temp are valid options to echo. | 64 | if (strrchr("neE", *p) == 0) { |
63 | * Handle them. | ||
64 | */ | ||
65 | while (*temp) | ||
66 | { | ||
67 | if (*temp == 'n') | ||
68 | nflag = 1; | ||
69 | else if (*temp == 'e') | ||
70 | eflag = 1; | ||
71 | else if (*temp == 'E') | ||
72 | eflag = 0; | ||
73 | else | ||
74 | goto just_echo; | 65 | goto just_echo; |
66 | } | ||
67 | } while (*++p); | ||
75 | 68 | ||
76 | temp++; | 69 | /* All of the options in this arg are valid, so handle them. */ |
77 | } | 70 | p = *argv + 1; |
78 | argc--; | 71 | do { |
79 | argv++; | 72 | if (*p == 'n') { |
73 | nflag = 0; | ||
74 | } else if (*p == 'e') { | ||
75 | eflag = '\\'; | ||
76 | } else { | ||
77 | eflag = 0; | ||
78 | } | ||
79 | } while (*++p); | ||
80 | } | 80 | } |
81 | 81 | ||
82 | just_echo: | 82 | just_echo: |
83 | while (argc > 0) { | 83 | #endif |
84 | const char *arg = argv[0]; | 84 | while (*argv) { |
85 | register int c; | 85 | register int c; |
86 | 86 | ||
87 | while ((c = *arg++)) { | 87 | while ((c = *(*argv)++)) { |
88 | 88 | if (c == eflag) { /* Check for escape seq. */ | |
89 | /* Check for escape sequence. */ | 89 | if (**argv == 'c') { |
90 | if (c == '\\' && eflag && *arg) { | 90 | /* '\c' means cancel newline and |
91 | if (*arg == 'c') { | 91 | * ignore all subsequent chars. */ |
92 | /* '\c' means cancel newline. */ | 92 | goto DONE; |
93 | nflag = 1; | 93 | } |
94 | arg++; | 94 | #ifndef CONFIG_FEATURE_FANCY_ECHO |
95 | continue; | 95 | /* SUSv3 specifies that octal escapes must begin with '0'. */ |
96 | } else { | 96 | if (((unsigned int)(**argv - '1')) >= 7) |
97 | c = process_escape_sequence(&arg); | 97 | #endif |
98 | { | ||
99 | /* Since SUSv3 mandates a first digit of 0, 4-digit octals | ||
100 | * of the form \0### are accepted. */ | ||
101 | if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) { | ||
102 | (*argv)++; | ||
103 | } | ||
104 | /* bb_process_escape_sequence can handle nul correctly */ | ||
105 | c = bb_process_escape_sequence((const char **) argv); | ||
98 | } | 106 | } |
99 | } | 107 | } |
100 | |||
101 | putchar(c); | 108 | putchar(c); |
102 | } | 109 | } |
103 | argc--; | 110 | |
104 | argv++; | 111 | if (*++argv) { |
105 | if (argc > 0) | ||
106 | putchar(' '); | 112 | putchar(' '); |
113 | } | ||
107 | } | 114 | } |
108 | if (!nflag) | 115 | |
116 | #ifdef CONFIG_FEATURE_FANCY_ECHO | ||
117 | if (nflag) { | ||
109 | putchar('\n'); | 118 | putchar('\n'); |
110 | fflush(stdout); | 119 | } |
120 | #else | ||
121 | putchar('\n'); | ||
122 | #endif | ||
111 | 123 | ||
112 | return EXIT_SUCCESS; | 124 | DONE: |
125 | bb_fflush_stdout_and_exit(EXIT_SUCCESS); | ||
113 | } | 126 | } |
114 | 127 | ||
115 | /*- | 128 | /*- |