source: branches/3.2/mindi-busybox/scripts/echo.c @ 3232

Last change on this file since 3232 was 2725, checked in by Bruno Cornec, 9 years ago
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
  • Property svn:eol-style set to native
File size: 5.8 KB
Line 
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
31#define WANT_HEX_ESCAPES 1
32
33/* Usual "this only works for ascii compatible encodings" disclaimer. */
34#undef _tolower
35#define _tolower(X) ((X)|((char) 0x20))
36
37static char bb_process_escape_sequence(const char **ptr)
38{
39    static const char charmap[] = {
40        'a',  'b',  'f',  'n',  'r',  't',  'v',  '\\', 0,
41        '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
42
43    const char *p;
44    const char *q;
45    unsigned int num_digits;
46    unsigned int r;
47    unsigned int n;
48    unsigned int d;
49    unsigned int base;
50
51    num_digits = n = 0;
52    base = 8;
53    q = *ptr;
54
55#ifdef WANT_HEX_ESCAPES
56    if (*q == 'x') {
57        ++q;
58        base = 16;
59        ++num_digits;
60    }
61#endif
62
63    do {
64        d = (unsigned char)(*q) - '0';
65#ifdef WANT_HEX_ESCAPES
66        if (d >= 10) {
67            d = (unsigned char)(_tolower(*q)) - 'a' + 10;
68        }
69#endif
70
71        if (d >= base) {
72#ifdef WANT_HEX_ESCAPES
73            if ((base == 16) && (!--num_digits)) {
74/*              return '\\'; */
75                --q;
76            }
77#endif
78            break;
79        }
80
81        r = n * base + d;
82        if (r > UCHAR_MAX) {
83            break;
84        }
85
86        n = r;
87        ++q;
88    } while (++num_digits < 3);
89
90    if (num_digits == 0) {  /* mnemonic escape sequence? */
91        p = charmap;
92        do {
93            if (*p == *q) {
94                q++;
95                break;
96            }
97        } while (*++p);
98        n = *(p + (sizeof(charmap)/2));
99    }
100
101    *ptr = q;
102
103    return (char) n;
104}
105
106
107int main(int argc, char **argv)
108{
109    const char *arg;
110    const char *p;
111    char nflag = 1;
112    char eflag = 0;
113
114    /* We must check that stdout is not closed. */
115    if (dup2(1, 1) != 1)
116        return -1;
117
118    while (1) {
119        arg = *++argv;
120        if (!arg)
121            goto newline_ret;
122        if (*arg != '-')
123            break;
124
125        /* If it appears that we are handling options, then make sure
126         * that all of the options specified are actually valid.
127         * Otherwise, the string should just be echoed.
128         */
129        p = arg + 1;
130        if (!*p)    /* A single '-', so echo it. */
131            goto just_echo;
132
133        do {
134            if (!strrchr("neE", *p))
135                goto just_echo;
136        } while (*++p);
137
138        /* All of the options in this arg are valid, so handle them. */
139        p = arg + 1;
140        do {
141            if (*p == 'n')
142                nflag = 0;
143            if (*p == 'e')
144                eflag = '\\';
145        } while (*++p);
146    }
147 just_echo:
148    while (1) {
149        /* arg is already == *argv and isn't NULL */
150        int c;
151
152        if (!eflag) {
153            /* optimization for very common case */
154            fputs(arg, stdout);
155        } else while ((c = *arg++)) {
156            if (c == eflag) {   /* Check for escape seq. */
157                if (*arg == 'c') {
158                    /* '\c' means cancel newline and
159                     * ignore all subsequent chars. */
160                    goto ret;
161                }
162                {
163                    /* Since SUSv3 mandates a first digit of 0, 4-digit octals
164                    * of the form \0### are accepted. */
165                    if (*arg == '0') {
166                        /* NB: don't turn "...\0" into "...\" */
167                        if (arg[1] && ((unsigned char)(arg[1]) - '0') < 8) {
168                            arg++;
169                        }
170                    }
171                    /* bb_process_escape_sequence handles NUL correctly
172                     * ("...\" case. */
173                    c = bb_process_escape_sequence(&arg);
174                }
175            }
176            putchar(c);
177        }
178
179        arg = *++argv;
180        if (!arg)
181            break;
182        putchar(' ');
183    }
184
185 newline_ret:
186    if (nflag) {
187        putchar('\n');
188    }
189 ret:
190    return fflush(NULL);
191}
192
193/*-
194 * Copyright (c) 1991, 1993
195 *      The Regents of the University of California.  All rights reserved.
196 *
197 * This code is derived from software contributed to Berkeley by
198 * Kenneth Almquist.
199 *
200 * Redistribution and use in source and binary forms, with or without
201 * modification, are permitted provided that the following conditions
202 * are met:
203 * 1. Redistributions of source code must retain the above copyright
204 *    notice, this list of conditions and the following disclaimer.
205 * 2. Redistributions in binary form must reproduce the above copyright
206 *    notice, this list of conditions and the following disclaimer in the
207 *    documentation and/or other materials provided with the distribution.
208 *
209 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
210 *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
211 *
212 *      California, Berkeley and its contributors.
213 * 4. Neither the name of the University nor the names of its contributors
214 *    may be used to endorse or promote products derived from this software
215 *    without specific prior written permission.
216 *
217 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
218 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
220 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
221 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
222 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
223 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
224 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
225 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
226 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
227 * SUCH DAMAGE.
228 *
229 *      @(#)echo.c      8.1 (Berkeley) 5/31/93
230 */
Note: See TracBrowser for help on using the repository browser.