Bug 32935

Summary: /bin/sh buildin echo command have invalid implimentation of command args parser
Product: Base System Reporter: Vladimir B.Grebenschikov <vova>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.0-CURRENT   
Hardware: Any   
OS: Any   

Description Vladimir B.Grebenschikov 2001-12-17 15:30:00 UTC
According to manpage sh(1):

     echo [-en] string
             Print string to the standard output with a newline appended.

             -n      Suppress the output of the trailing newline.

             -e      Process C-style backslash escape sequences.  echo under-
                     stands the following character escapes:

But in realality echo accepts either -n or -e flag but not both simultaneously.

Fix: diff -u src/bin/sh/bltin/echo.c:1.9.2.1
src/bin/sh/bltin/echo.c:1.9.2.1.10000.2


--
SWSoft, Moscow
Vladimir B. Grebenschikov vova@sw.ru--aPitJT3o4KGa2V3P9FmY1yAnVu1LjqcvzJXIyNHGkS2gQz1g
Content-Type: text/plain; name="file.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="file.diff"

--- src/bin/sh/bltin/echo.c:1.9.2.1     Fri Jun 30 00:51:59 2000
+++ src/bin/sh/bltin/echo.c     Mon Dec 17 18:15:23 2001
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)echo.c      8.2 (Berkeley) 5/4/95
- * $FreeBSD: src/bin/sh/bltin/echo.c,v 1.9.2.1 2000/06/29 20:51:59 mph Exp
$
+ * $FreeBSD: src/bin/sh/bltin/echo.c,v 1.9.2.1.10000.2 2001/12/17 15:15:23
kmv Exp $
  */
 
 /*
@@ -64,16 +64,28 @@
        ap = argv;
        if (argc)
                ap++;
-       if ((p = *ap) != NULL) {
-               if (equal(p, "-n")) {
-                       nflag++;
-                       ap++;
-               } else if (equal(p, "-e")) {
+       if ((p = *ap) != NULL && *p == '-') {
+               ap++;
+               p++;
+               do {
+                       if (*p == 'n') { 
+                               nflag++;
+                       }
+#ifndef eflag
+                       else if (*p == 'e') {
+                               eflag++;
+                       }
+#endif
+                       else {
+                               nflag = 0;
 #ifndef eflag
-                       eflag++;
+                               eflag = 0;
 #endif
-                       ap++;
-               }
+                               ap--;
+                               break;
+                       }
+                       p++;
+               } while (*p); 
        }
        while ((p = *ap++) != NULL) {
                while ((c = *p++) != '\0') {
How-To-Repeat: 
$ echo -en  "\tGGG\nJJJ\nccc"
-en \tGGG\nJJJ\nccc
$ 

but:

$ echo -e  "\tGGG\nJJJ\nccc"
        GGG
JJJ
ccc
$

$ echo -n "test"
test$
Comment 1 Sheldon Hearn 2001-12-30 13:42:53 UTC
On Mon, 17 Dec 2001 18:27:02 +0300, "Vladimir B.Grebenschikov" wrote:

> >Number:         32935
> >Category:       bin
> >Synopsis:       /bin/sh buildin echo command have invalid implimentation of command args parser

I've asked for review on the freebsd-audit mailing list.  Hopefully,
you'll get feedback soon.

Ciao,
Sheldon.
Comment 2 mheffner 2001-12-31 08:05:51 UTC
On 30-Dec-2001 Sheldon Hearn wrote:
| 
| Hi folks,
| 
| Could someone check out PR bin/32935, which contains a patch to fix
| ash's builtin echo command so that it accepts the -e and -n options
| combined?
| 

Looks ok, except that I think in the '#define eflag 1' case it should
still accept '-ne' as valid and just ignore the 'e'. How about this:


Index: echo.c
===================================================================
RCS file: /home/ncvs/src/bin/sh/bltin/echo.c,v
retrieving revision 1.10
diff -u -r1.10 echo.c
--- echo.c      26 Jun 2000 22:43:30 -0000      1.10
+++ echo.c      31 Dec 2001 08:00:09 -0000
@@ -64,16 +64,28 @@
        ap = argv;
        if (argc)
                ap++;
-       if ((p = *ap) != NULL) {
-               if (equal(p, "-n")) {
-                       nflag++;
-                       ap++;
-               } else if (equal(p, "-e")) {
+       if ((p = *ap) != NULL && *p == '-') {
+               ap++;
+               p++;
+               do {
+                       if (*p == 'n')
+                               nflag++;
+                       else if (*p == 'e')
 #ifndef eflag
-                       eflag++;
+                               eflag++;
+#else
+                               ;
 #endif
-                       ap++;
-               }
+                       else {
+                               nflag = 0;
+#ifndef eflag
+                               eflag = 0;
+#endif
+                               ap--;
+                               break;
+                       }
+               } while (*++p != '\0');
+                       
        }
        while ((p = *ap++) != NULL) {
                while ((c = *p++) != '\0') {



Mike

-- 
  Mike Heffner     <mheffner@[acm.]vt.edu>
  Fredericksburg, VA   <mikeh@FreeBSD.org>
Comment 3 Sheldon Hearn 2001-12-31 09:16:45 UTC
On Mon, 31 Dec 2001 03:05:51 EST, Mike Heffner wrote:

> Looks ok, except that I think in the '#define eflag 1' case it should
> still accept '-ne' as valid and just ignore the 'e'. How about this:

Thanks, Mike.

But why would you want to accept an option that you don't support?

Personally, I don't think -e support needs to be optional. :-)

Ciao,
Sheldon.
Comment 4 mheffner 2001-12-31 16:46:20 UTC
On 31-Dec-2001 Sheldon Hearn wrote:
| 
| 
| On Mon, 31 Dec 2001 03:05:51 EST, Mike Heffner wrote:
| 
|> Looks ok, except that I think in the '#define eflag 1' case it should
|> still accept '-ne' as valid and just ignore the 'e'. How about this:
| 
| Thanks, Mike.
| 
| But why would you want to accept an option that you don't support?
| 
| Personally, I don't think -e support needs to be optional. :-)
| 

Well, I guess I'm not sure as to the context of when the defined eflag
override is used. IMO, if a shell script is using 'echo -e blah', then it
shouldn't break on an 'echo' that has been compiled with the eflag
implicitly enabled. Also, I was just following the original broken code, so
that the previous test case would work as before. ;)

Mike

-- 
  Mike Heffner     <mheffner@[acm.]vt.edu>
  Fredericksburg, VA   <mikeh@FreeBSD.org>
Comment 5 Tim Robbins freebsd_committer freebsd_triage 2002-07-20 05:39:26 UTC
State Changed
From-To: open->patched

Manual page has been updated to indicate that only one of -n and -e may 
be specified. The traditional BSD behaviour will not be changed. Consider 
using printf(1) instead to print escape sequences or omit the trailing 
newline, it is much more consistent between operating systems.
Comment 6 Tim Robbins freebsd_committer freebsd_triage 2002-07-28 11:24:27 UTC
State Changed
From-To: patched->closed

Change has been MFC'd.