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
This commit is contained in:
23
check.t
23
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: 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: 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 $
|
# $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
|
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||||
|
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
@(#)MIRBSD KSH R39 2009/10/04
|
@(#)MIRBSD KSH R39 2009/10/10
|
||||||
description:
|
description:
|
||||||
Check version of shell.
|
Check version of shell.
|
||||||
stdin:
|
stdin:
|
||||||
@@ -6571,3 +6571,22 @@ stdin:
|
|||||||
expected-stdout:
|
expected-stdout:
|
||||||
fxbar 0
|
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
|
||||||
|
---
|
||||||
|
59
funcs.c
59
funcs.c
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#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
|
#if HAVE_KILLPG
|
||||||
/*
|
/*
|
||||||
@@ -507,31 +507,38 @@ c_print(const char **wp)
|
|||||||
#define PO_PMINUSMINUS BIT(2) /* print a -- argument */
|
#define PO_PMINUSMINUS BIT(2) /* print a -- argument */
|
||||||
#define PO_HIST BIT(3) /* print to history instead of stdout */
|
#define PO_HIST BIT(3) /* print to history instead of stdout */
|
||||||
#define PO_COPROC BIT(4) /* printing to coprocess: block SIGPIPE */
|
#define PO_COPROC BIT(4) /* printing to coprocess: block SIGPIPE */
|
||||||
int fd = 1;
|
int fd = 1, c;
|
||||||
int flags = PO_EXPAND|PO_NL;
|
int flags = PO_EXPAND|PO_NL;
|
||||||
const char *s, *emsg;
|
const char *s, *emsg;
|
||||||
XString xs;
|
XString xs;
|
||||||
char *xp;
|
char *xp;
|
||||||
|
|
||||||
if (wp[0][0] == 'e') { /* echo command */
|
if (wp[0][0] == 'e') {
|
||||||
int nflags = flags;
|
/* echo builtin */
|
||||||
|
wp++;
|
||||||
/* 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 (Flag(FSH)) {
|
if (Flag(FSH)) {
|
||||||
if (*wp && strcmp(*wp, "-n") == 0) {
|
/* Debian Policy 10.4 compliant "echo" builtin */
|
||||||
flags &= ~PO_NL;
|
if (*wp && !strcmp(*wp, "-n")) {
|
||||||
|
/* we recognise "-n" only as the first arg */
|
||||||
|
flags = 0;
|
||||||
wp++;
|
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 = *wp) && *s == '-' && s[1]) {
|
||||||
while (*++s)
|
while (*++s)
|
||||||
if (*s == 'n')
|
if (*s == 'n')
|
||||||
@@ -546,14 +553,17 @@ c_print(const char **wp)
|
|||||||
* nflags, print argument
|
* nflags, print argument
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (*s)
|
if (*s)
|
||||||
break;
|
break;
|
||||||
wp++;
|
wp++;
|
||||||
flags = nflags;
|
flags = nflags;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int optc;
|
int optc;
|
||||||
const char *opts = "Rnprsu,";
|
const char *opts = "Rnprsu,";
|
||||||
|
|
||||||
while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
|
while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1)
|
||||||
switch (optc) {
|
switch (optc) {
|
||||||
case 'R': /* fake BSD echo command */
|
case 'R': /* fake BSD echo command */
|
||||||
@@ -590,6 +600,7 @@ c_print(const char **wp)
|
|||||||
case '?':
|
case '?':
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(builtin_opt.info & GI_MINUSMINUS)) {
|
if (!(builtin_opt.info & GI_MINUSMINUS)) {
|
||||||
/* treat a lone - like -- */
|
/* treat a lone - like -- */
|
||||||
if (wp[builtin_opt.optind] &&
|
if (wp[builtin_opt.optind] &&
|
||||||
@@ -603,7 +614,6 @@ c_print(const char **wp)
|
|||||||
Xinit(xs, xp, 128, ATEMP);
|
Xinit(xs, xp, 128, ATEMP);
|
||||||
|
|
||||||
while (*wp != NULL) {
|
while (*wp != NULL) {
|
||||||
int c;
|
|
||||||
s = *wp;
|
s = *wp;
|
||||||
while ((c = *s++) != '\0') {
|
while ((c = *s++) != '\0') {
|
||||||
Xcheck(xs, xp);
|
Xcheck(xs, xp);
|
||||||
@@ -649,7 +659,7 @@ c_print(const char **wp)
|
|||||||
histsave(&source->line, Xstring(xs, xp), true, false);
|
histsave(&source->line, Xstring(xs, xp), true, false);
|
||||||
Xfree(xs, xp);
|
Xfree(xs, xp);
|
||||||
} else {
|
} else {
|
||||||
int n, len = Xlength(xs, xp);
|
int len = Xlength(xs, xp);
|
||||||
int opipe = 0;
|
int opipe = 0;
|
||||||
|
|
||||||
/* Ensure we aren't killed by a SIGPIPE while writing to
|
/* Ensure we aren't killed by a SIGPIPE while writing to
|
||||||
@@ -662,8 +672,7 @@ c_print(const char **wp)
|
|||||||
opipe = block_pipe();
|
opipe = block_pipe();
|
||||||
}
|
}
|
||||||
for (s = Xstring(xs, xp); len > 0; ) {
|
for (s = Xstring(xs, xp); len > 0; ) {
|
||||||
n = write(fd, s, len);
|
if ((c = write(fd, s, len)) < 0) {
|
||||||
if (n < 0) {
|
|
||||||
if (flags & PO_COPROC)
|
if (flags & PO_COPROC)
|
||||||
restore_pipe(opipe);
|
restore_pipe(opipe);
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
@@ -675,8 +684,8 @@ c_print(const char **wp)
|
|||||||
}
|
}
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
s += n;
|
s += c;
|
||||||
len -= n;
|
len -= c;
|
||||||
}
|
}
|
||||||
if (flags & PO_COPROC)
|
if (flags & PO_COPROC)
|
||||||
restore_pipe(opipe);
|
restore_pipe(opipe);
|
||||||
|
8
mksh.1
8
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 $
|
.\" $OpenBSD: ksh.1,v 1.129 2009/05/28 06:09:06 jmc Exp $
|
||||||
.\"-
|
.\"-
|
||||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
|
.el .xD \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
|
||||||
..
|
..
|
||||||
.\"-
|
.\"-
|
||||||
.Dd $Mdocdate: October 2 2009 $
|
.Dd $Mdocdate: October 10 2009 $
|
||||||
.Dt MKSH 1
|
.Dt MKSH 1
|
||||||
.Os MirBSD
|
.Os MirBSD
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -2694,7 +2694,7 @@ assignments are performed and exported for the duration of the command.
|
|||||||
.Pp
|
.Pp
|
||||||
The following describes the special and regular built-in commands:
|
The following describes the special and regular built-in commands:
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width Ds -compact
|
.Bl -tag -width false -compact
|
||||||
.It Ic \&. Ar file Op Ar arg ...
|
.It Ic \&. Ar file Op Ar arg ...
|
||||||
This is called the
|
This is called the
|
||||||
.Dq dot
|
.Dq dot
|
||||||
@@ -3034,6 +3034,8 @@ If the
|
|||||||
option is set, only the first argument is treated as an option, and only
|
option is set, only the first argument is treated as an option, and only
|
||||||
if it is exactly
|
if it is exactly
|
||||||
.Dq Fl n .
|
.Dq Fl n .
|
||||||
|
Backslash interpretation is disabled.
|
||||||
|
.Pp
|
||||||
.It Ic eval Ar command ...
|
.It Ic eval Ar command ...
|
||||||
The arguments are concatenated (with spaces between them) to form a single
|
The arguments are concatenated (with spaces between them) to form a single
|
||||||
string which the shell then parses and executes in the current environment.
|
string which the shell then parses and executes in the current environment.
|
||||||
|
4
sh.h
4
sh.h
@@ -134,9 +134,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#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
|
#endif
|
||||||
#define MKSH_VERSION "R39 2009/10/04"
|
#define MKSH_VERSION "R39 2009/10/10"
|
||||||
|
|
||||||
#ifndef MKSH_INCLUDES_ONLY
|
#ifndef MKSH_INCLUDES_ONLY
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user