httpd: do disable header reading timeout even if proxying
[oweals/busybox.git] / scripts / echo.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * echo implementation for busybox - used as a helper for testsuite/*
4  * on systems lacking "echo -en"
5  *
6  * Copyright (c) 1991, 1993
7  *      The Regents of the University of California.  All rights reserved.
8  *
9  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10  *
11  * Original copyright notice is retained at the end of this file.
12  */
13
14 /* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */
15 /* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */
16
17 /* Mar 16, 2003      Manuel Novoa III   (mjn3@codepoet.org)
18  *
19  * Because of behavioral differences, implemented configurable SUSv3
20  * or 'fancy' gnu-ish behaviors.  Also, reduced size and fixed bugs.
21  * 1) In handling '\c' escape, the previous version only suppressed the
22  *     trailing newline.  SUSv3 specifies _no_ output after '\c'.
23  * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}.
24  *    The previous version did not allow 4-digit octals.
25  */
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <limits.h>
30 #include <unistd.h>
31
32 #define WANT_HEX_ESCAPES 1
33
34 /* Usual "this only works for ascii compatible encodings" disclaimer. */
35 #undef _tolower
36 #define _tolower(X) ((X)|((char) 0x20))
37
38 static char bb_process_escape_sequence(const char **ptr)
39 {
40         static const char charmap[] = {
41                 'a',  'b',  'f',  'n',  'r',  't',  'v',  '\\', 0,
42                 '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
43
44         const char *p;
45         const char *q;
46         unsigned int num_digits;
47         unsigned int r;
48         unsigned int n;
49         unsigned int d;
50         unsigned int base;
51
52         num_digits = n = 0;
53         base = 8;
54         q = *ptr;
55
56 #ifdef WANT_HEX_ESCAPES
57         if (*q == 'x') {
58                 ++q;
59                 base = 16;
60                 ++num_digits;
61         }
62 #endif
63
64         do {
65                 d = (unsigned char)(*q) - '0';
66 #ifdef WANT_HEX_ESCAPES
67                 if (d >= 10) {
68                         d = (unsigned char)(_tolower(*q)) - 'a' + 10;
69                 }
70 #endif
71
72                 if (d >= base) {
73 #ifdef WANT_HEX_ESCAPES
74                         if ((base == 16) && (!--num_digits)) {
75 /*                              return '\\'; */
76                                 --q;
77                         }
78 #endif
79                         break;
80                 }
81
82                 r = n * base + d;
83                 if (r > UCHAR_MAX) {
84                         break;
85                 }
86
87                 n = r;
88                 ++q;
89         } while (++num_digits < 3);
90
91         if (num_digits == 0) {  /* mnemonic escape sequence? */
92                 p = charmap;
93                 do {
94                         if (*p == *q) {
95                                 q++;
96                                 break;
97                         }
98                 } while (*++p);
99                 n = *(p + (sizeof(charmap)/2));
100         }
101
102         *ptr = q;
103
104         return (char) n;
105 }
106
107
108 int main(int argc, char **argv)
109 {
110         const char *arg;
111         const char *p;
112         char nflag = 1;
113         char eflag = 0;
114
115         /* We must check that stdout is not closed. */
116         if (dup2(1, 1) != 1)
117                 return -1;
118
119         while (1) {
120                 arg = *++argv;
121                 if (!arg)
122                         goto newline_ret;
123                 if (*arg != '-')
124                         break;
125
126                 /* If it appears that we are handling options, then make sure
127                  * that all of the options specified are actually valid.
128                  * Otherwise, the string should just be echoed.
129                  */
130                 p = arg + 1;
131                 if (!*p)        /* A single '-', so echo it. */
132                         goto just_echo;
133
134                 do {
135                         if (!strrchr("neE", *p))
136                                 goto just_echo;
137                 } while (*++p);
138
139                 /* All of the options in this arg are valid, so handle them. */
140                 p = arg + 1;
141                 do {
142                         if (*p == 'n')
143                                 nflag = 0;
144                         if (*p == 'e')
145                                 eflag = '\\';
146                 } while (*++p);
147         }
148  just_echo:
149         while (1) {
150                 /* arg is already == *argv and isn't NULL */
151                 int c;
152
153                 if (!eflag) {
154                         /* optimization for very common case */
155                         fputs(arg, stdout);
156                 } else while ((c = *arg++)) {
157                         if (c == eflag) {       /* Check for escape seq. */
158                                 if (*arg == 'c') {
159                                         /* '\c' means cancel newline and
160                                          * ignore all subsequent chars. */
161                                         goto ret;
162                                 }
163                                 {
164                                         /* Since SUSv3 mandates a first digit of 0, 4-digit octals
165                                         * of the form \0### are accepted. */
166                                         if (*arg == '0') {
167                                                 /* NB: don't turn "...\0" into "...\" */
168                                                 if (arg[1] && ((unsigned char)(arg[1]) - '0') < 8) {
169                                                         arg++;
170                                                 }
171                                         }
172                                         /* bb_process_escape_sequence handles NUL correctly
173                                          * ("...\" case. */
174                                         c = bb_process_escape_sequence(&arg);
175                                 }
176                         }
177                         putchar(c);
178                 }
179
180                 arg = *++argv;
181                 if (!arg)
182                         break;
183                 putchar(' ');
184         }
185
186  newline_ret:
187         if (nflag) {
188                 putchar('\n');
189         }
190  ret:
191         return fflush(NULL);
192 }
193
194 /*-
195  * Copyright (c) 1991, 1993
196  *      The Regents of the University of California.  All rights reserved.
197  *
198  * This code is derived from software contributed to Berkeley by
199  * Kenneth Almquist.
200  *
201  * Redistribution and use in source and binary forms, with or without
202  * modification, are permitted provided that the following conditions
203  * are met:
204  * 1. Redistributions of source code must retain the above copyright
205  *    notice, this list of conditions and the following disclaimer.
206  * 2. Redistributions in binary form must reproduce the above copyright
207  *    notice, this list of conditions and the following disclaimer in the
208  *    documentation and/or other materials provided with the distribution.
209  *
210  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
211  *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
212  *
213  *      California, Berkeley and its contributors.
214  * 4. Neither the name of the University nor the names of its contributors
215  *    may be used to endorse or promote products derived from this software
216  *    without specific prior written permission.
217  *
218  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
219  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
220  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
221  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
222  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
223  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
224  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
225  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
226  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
227  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
228  * SUCH DAMAGE.
229  *
230  *      @(#)echo.c      8.1 (Berkeley) 5/31/93
231  */