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:
tg
2009-10-10 21:17:31 +00:00
parent b4a32ff5f7
commit 549888a183
4 changed files with 62 additions and 32 deletions

59
funcs.c
View File

@@ -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);