use bb_fflush_stdout_and_exit instead of exit
[oweals/busybox.git] / coreutils / echo.c
index 6e279d1c6d332431249039bc7909ed76be635049..539640fb0052eb3d42f05324d8d05f706db86a15 100644 (file)
  * Original copyright notice is retained at the end of this file.
  */
 
-#include "internal.h"
-#include <stdio.h>
+/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */
 
-static const char uname_usage[] =
-       "echo [-neE] [ARG ...]\n"
-#ifndef BB_FEATURE_TRIVIAL_HELP
-       "\nPrints the specified ARGs to stdout\n\n"
-       "Options:\n"
-       "\t-n\tsuppress trailing newline\n"
-       "\t-e\tinterpret backslash-escaped characters (i.e. \\t=tab etc)\n"
-       "\t-E\tdisable interpretation of backslash-escaped characters\n"
-#endif
-       ;
+/* Mar 16, 2003      Manuel Novoa III   (mjn3@codepoet.org)
+ *
+ * Because of behavioral differences, implemented configurable SUSv3
+ * or 'fancy' gnu-ish behaviors.  Also, reduced size and fixed bugs.
+ * 1) In handling '\c' escape, the previous version only suppressed the
+ *     trailing newline.  SUSv3 specifies _no_ output after '\c'.
+ * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}.
+ *    The previous version version did not allow 4-digit octals.
+ */
 
-extern int 
-echo_main(int argc, char** argv)
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "busybox.h"
+
+extern int echo_main(int argc, char** argv)
 {
-       register char **ap;
-       char *p;
-       register char c;
-       int nflag = 0;
+#ifndef CONFIG_FEATURE_FANCY_ECHO
+#define eflag '\\'
+       ++argv;
+#else
+       const char *p;
+       int nflag = 1;
        int eflag = 0;
 
-       ap = argv;
-       if (argc)
-               ap++;
-       while ((p = *ap) != NULL && *p == '-') {
-               if (strcmp(p, "-n")==0) {
-                       nflag = 1;
-               } else if (strcmp(p, "-e")==0) {
-                       eflag = 1;
-               } else if (strcmp(p, "-E")==0) {
-                       eflag = 0;
+       while (*++argv && (**argv == '-')) {
+               /* If it appears that we are handling options, then make sure
+                * that all of the options specified are actually valid.
+                * Otherwise, the string should just be echoed.
+                */
+
+               if (!*(p = *argv + 1)) {        /* A single '-', so echo it. */
+                       goto just_echo;
                }
-               else if (strncmp(p, "--", 2)==0) {
-                       usage( uname_usage);
-               } 
-               else break;
-               ap++;
+
+               do {
+                       if (strrchr("neE", *p) == 0) {
+                               goto just_echo;
+                       }
+               } while (*++p);
+
+               /* All of the options in this arg are valid, so handle them. */
+               p = *argv + 1;
+               do {
+                       if (*p == 'n') {
+                               nflag = 0;
+                       } else if (*p == 'e') {
+                               eflag = '\\';
+                       } else {
+                               eflag = 0;
+                       }
+               } while (*++p);
        }
-       while ((p = *ap++) != NULL) {
-               while ((c = *p++) != '\0') {
-                       if (c == '\\' && eflag) {
-                               if (*p == 'c')
-                                       exit(0);
-                               else
-                                       c = process_escape_sequence(&p);
+
+just_echo:
+#endif
+       while (*argv) {
+               register int c;
+
+               while ((c = *(*argv)++)) {
+                       if (c == eflag) {       /* Check for escape seq. */
+                               if (**argv == 'c') {
+                                       /* '\c' means cancel newline and
+                                        * ignore all subsequent chars. */
+                                       goto DONE;
+                               }
+#ifndef CONFIG_FEATURE_FANCY_ECHO
+                               /* SUSv3 specifies that octal escapes must begin with '0'. */
+                               if (((unsigned int)(**argv - '1')) >= 7)
+#endif
+                               {
+                                       /* Since SUSv3 mandates a first digit of 0, 4-digit octals
+                                       * of the form \0### are accepted. */
+                                       if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) {
+                                               (*argv)++;
+                                       }
+                                       /* bb_process_escape_sequence can handle nul correctly */
+                                       c = bb_process_escape_sequence((const char **) argv);
+                               }
                        }
                        putchar(c);
                }
-               if (*ap)
+
+               if (*++argv) {
                        putchar(' ');
+               }
        }
-       if (! nflag)
+
+#ifdef CONFIG_FEATURE_FANCY_ECHO
+       if (nflag) {
                putchar('\n');
-       fflush(stdout);
-       return( 0);
+       }
+#else
+       putchar('\n');
+#endif
+
+DONE:
+       bb_fflush_stdout_and_exit(EXIT_SUCCESS);
 }
 
 /*-
@@ -96,9 +140,10 @@ echo_main(int argc, char** argv)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
+ *
+ * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
+ *             ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
+ *
  *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
@@ -118,5 +163,3 @@ echo_main(int argc, char** argv)
  *
  *     @(#)echo.c      8.1 (Berkeley) 5/31/93
  */
-
-