From 549888a183bcf19f4cbdd63408a1caf79098a6bb Mon Sep 17 00:00:00 2001 From: tg Date: Sat, 10 Oct 2009 21:17:31 +0000 Subject: [PATCH] while testing haserl-0.9.26 on MirBSD, I discovered that the echo builtin in FSH mode did in fact, contrary to POSIX and Debian Policy 10.4 behavi- our (I think), interpret escape sequences; fix and add testsuite for echo --- check.t | 23 ++++++++++++++++++++-- funcs.c | 59 +++++++++++++++++++++++++++++++++------------------------ mksh.1 | 8 +++++--- sh.h | 4 ++-- 4 files changed, 62 insertions(+), 32 deletions(-) diff --git a/check.t b/check.t index 885181e..9c7ae8a 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.320 2009/10/10 17:39:48 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.321 2009/10/10 21:17:28 tg Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ @@ -25,7 +25,7 @@ # http://www.research.att.com/~gsf/public/ifs.sh expected-stdout: - @(#)MIRBSD KSH R39 2009/10/04 + @(#)MIRBSD KSH R39 2009/10/10 description: Check version of shell. stdin: @@ -6571,3 +6571,22 @@ stdin: expected-stdout: fxbar 0 --- +name: echo-test-1 +description: + Test what the echo builtin does (mksh) +stdin: + echo -n 'foo\x40bar' + echo -e '\tbaz' +expected-stdout: + foo@bar baz +--- +name: echo-test-2 +description: + Test what the echo builtin does (POSIX) +arguments: !-o!sh! +stdin: + echo -n 'foo\x40bar' + echo -e '\tbaz' +expected-stdout: + foo\x40bar-e \tbaz +--- diff --git a/funcs.c b/funcs.c index 2a3ab5e..c2abfa8 100644 --- a/funcs.c +++ b/funcs.c @@ -25,7 +25,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.136 2009/10/02 18:08:33 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.137 2009/10/10 21:17:29 tg Exp $"); #if HAVE_KILLPG /* @@ -507,31 +507,38 @@ c_print(const char **wp) #define PO_PMINUSMINUS BIT(2) /* print a -- argument */ #define PO_HIST BIT(3) /* print to history instead of stdout */ #define PO_COPROC BIT(4) /* printing to coprocess: block SIGPIPE */ - int fd = 1; + int fd = 1, c; int flags = PO_EXPAND|PO_NL; const char *s, *emsg; XString xs; char *xp; - if (wp[0][0] == 'e') { /* echo command */ - int nflags = flags; - - /* A compromise between sysV and BSD echo commands: - * escape sequences are enabled by default, and - * -n, -e and -E are recognised if they appear - * in arguments with no illegal options (ie, echo -nq - * will print -nq). - * Different from sysV echo since options are recognised, - * different from BSD echo since escape sequences are enabled - * by default. - */ - wp += 1; + if (wp[0][0] == 'e') { + /* echo builtin */ + wp++; if (Flag(FSH)) { - if (*wp && strcmp(*wp, "-n") == 0) { - flags &= ~PO_NL; + /* Debian Policy 10.4 compliant "echo" builtin */ + if (*wp && !strcmp(*wp, "-n")) { + /* we recognise "-n" only as the first arg */ + flags = 0; wp++; - } - } else + } else + /* otherwise, we print everything as-is */ + flags = PO_NL; + } else { + int nflags = flags; + + /** + * a compromise between sysV and BSD echo commands: + * escape sequences are enabled by default, and -n, + * -e and -E are recognised if they appear in argu- + * ments with no illegal options (ie, echo -nq will + * print -nq). + * Different from sysV echo since options are reco- + * gnised, different from BSD echo since escape se- + * quences are enabled by default. + */ + while ((s = *wp) && *s == '-' && s[1]) { while (*++s) if (*s == 'n') @@ -546,14 +553,17 @@ c_print(const char **wp) * nflags, print argument */ break; + if (*s) break; wp++; flags = nflags; } + } } else { int optc; const char *opts = "Rnprsu,"; + while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1) switch (optc) { case 'R': /* fake BSD echo command */ @@ -590,6 +600,7 @@ c_print(const char **wp) case '?': return (1); } + if (!(builtin_opt.info & GI_MINUSMINUS)) { /* treat a lone - like -- */ if (wp[builtin_opt.optind] && @@ -603,7 +614,6 @@ c_print(const char **wp) Xinit(xs, xp, 128, ATEMP); while (*wp != NULL) { - int c; s = *wp; while ((c = *s++) != '\0') { Xcheck(xs, xp); @@ -649,7 +659,7 @@ c_print(const char **wp) histsave(&source->line, Xstring(xs, xp), true, false); Xfree(xs, xp); } else { - int n, len = Xlength(xs, xp); + int len = Xlength(xs, xp); int opipe = 0; /* Ensure we aren't killed by a SIGPIPE while writing to @@ -662,8 +672,7 @@ c_print(const char **wp) opipe = block_pipe(); } for (s = Xstring(xs, xp); len > 0; ) { - n = write(fd, s, len); - if (n < 0) { + if ((c = write(fd, s, len)) < 0) { if (flags & PO_COPROC) restore_pipe(opipe); if (errno == EINTR) { @@ -675,8 +684,8 @@ c_print(const char **wp) } return (1); } - s += n; - len -= n; + s += c; + len -= c; } if (flags & PO_COPROC) restore_pipe(opipe); diff --git a/mksh.1 b/mksh.1 index f92406b..5924dad 100644 --- a/mksh.1 +++ b/mksh.1 @@ -1,4 +1,4 @@ -.\" $MirOS: src/bin/mksh/mksh.1,v 1.193 2009/10/02 18:08:35 tg Exp $ +.\" $MirOS: src/bin/mksh/mksh.1,v 1.194 2009/10/10 21:17:30 tg Exp $ .\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $ .\"- .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 @@ -48,7 +48,7 @@ .el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 .. .\"- -.Dd $Mdocdate: October 2 2009 $ +.Dd $Mdocdate: October 10 2009 $ .Dt MKSH 1 .Os MirBSD .Sh NAME @@ -2694,7 +2694,7 @@ assignments are performed and exported for the duration of the command. .Pp The following describes the special and regular built-in commands: .Pp -.Bl -tag -width Ds -compact +.Bl -tag -width false -compact .It Ic \&. Ar file Op Ar arg ... This is called the .Dq dot @@ -3034,6 +3034,8 @@ If the option is set, only the first argument is treated as an option, and only if it is exactly .Dq Fl n . +Backslash interpretation is disabled. +.Pp .It Ic eval Ar command ... The arguments are concatenated (with spaces between them) to form a single string which the shell then parses and executes in the current environment. diff --git a/sh.h b/sh.h index 73a33d8..16c45cd 100644 --- a/sh.h +++ b/sh.h @@ -134,9 +134,9 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.353 2009/10/04 13:19:33 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.354 2009/10/10 21:17:31 tg Exp $"); #endif -#define MKSH_VERSION "R39 2009/10/04" +#define MKSH_VERSION "R39 2009/10/10" #ifndef MKSH_INCLUDES_ONLY