fix errno in print/echo builtin; optimise (with partial rewrite)

This commit is contained in:
tg 2016-01-20 21:34:13 +00:00
parent 9167be0584
commit 61f7661b92
4 changed files with 104 additions and 105 deletions

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.720 2016/01/19 23:12:10 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.721 2016/01/20 21:34:09 tg Exp $
# -*- mode: sh -*- # -*- mode: sh -*-
#- #-
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
@ -30,7 +30,7 @@
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date # (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R52 2016/01/19 @(#)MIRBSD KSH R52 2016/01/20
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -39,7 +39,7 @@ name: KSH_VERSION
category: shell:legacy-no category: shell:legacy-no
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R52 2016/01/19 @(#)LEGACY KSH R52 2016/01/20
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:

162
funcs.c
View File

@ -38,7 +38,7 @@
#endif #endif
#endif #endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.292 2016/01/20 20:29:48 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.293 2016/01/20 21:34:11 tg Exp $");
#if HAVE_KILLPG #if HAVE_KILLPG
/* /*
@ -278,20 +278,18 @@ static void s_put(int);
int int
c_print(const char **wp) c_print(const char **wp)
{ {
#define PO_NL BIT(0) /* print newline */
#define PO_EXPAND BIT(1) /* expand backslash sequences */
#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, c; int fd = 1, c;
int flags = PO_EXPAND | PO_NL; const char *s;
const char *s, *emsg;
XString xs; XString xs;
char *xp; char *xp;
/* print newline; expand backslash sequences */
bool po_nl = true, po_exp = true;
/* print to history instead of file descriptor / stdout */
bool po_hist = false;
if (wp[0][0] == 'e') { if (wp[0][0] == 'e') {
/* echo builtin */ /* "echo" builtin */
wp++; ++wp;
#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT #ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
if (Flag(FSH)) { if (Flag(FSH)) {
/* /*
@ -299,7 +297,7 @@ c_print(const char **wp)
* one that supports -e but does not enable it by * one that supports -e but does not enable it by
* default * default
*/ */
flags = PO_NL; po_exp = false;
} }
#endif #endif
if (Flag(FPOSIX) || if (Flag(FPOSIX) ||
@ -309,14 +307,14 @@ c_print(const char **wp)
Flag(FAS_BUILTIN)) { Flag(FAS_BUILTIN)) {
/* Debian Policy 10.4 compliant "echo" builtin */ /* Debian Policy 10.4 compliant "echo" builtin */
if (*wp && !strcmp(*wp, "-n")) { if (*wp && !strcmp(*wp, "-n")) {
/* we recognise "-n" only as the first arg */ /* recognise "-n" only as the first arg */
flags = 0; po_nl = false;
wp++; ++wp;
} else }
/* otherwise, we print everything as-is */ /* print everything as-is */
flags = PO_NL; po_exp = false;
} else { } else {
int nflags = flags; bool new_exp = po_exp, new_nl = po_nl;
/** /**
* a compromise between sysV and BSD echo commands: * a compromise between sysV and BSD echo commands:
@ -329,62 +327,65 @@ c_print(const char **wp)
* quences are enabled by default. * quences are enabled by default.
*/ */
while ((s = *wp) && *s == '-' && s[1]) { print_tradparse_arg:
while (*++s) if ((s = *wp) && *s++ == '-' && *s) {
if (*s == 'n') print_tradparse_ch:
nflags &= ~PO_NL; switch ((c = *s++)) {
else if (*s == 'e') case 'E':
nflags |= PO_EXPAND; new_exp = false;
else if (*s == 'E') goto print_tradparse_ch;
nflags &= ~PO_EXPAND; case 'e':
else new_exp = true;
/* goto print_tradparse_ch;
* bad option: don't use case 'n':
* nflags, print argument new_nl = false;
*/ goto print_tradparse_ch;
break; case '\0':
po_exp = new_exp;
if (*s) po_nl = new_nl;
break; ++wp;
wp++; goto print_tradparse_arg;
flags = nflags; }
} }
} }
} else { } else {
int optc; /* "print" builtin */
const char *opts = "Rnprsu,"; const char *opts = "npRrsu,";
const char *emsg;
/* print a "--" argument */
bool po_pminusminus = false;
while ((optc = ksh_getopt(wp, &builtin_opt, opts)) != -1) while ((c = ksh_getopt(wp, &builtin_opt, opts)) != -1)
switch (optc) { switch (c) {
case 'R':
/* fake BSD echo command */
flags |= PO_PMINUSMINUS;
flags &= ~PO_EXPAND;
opts = "ne";
break;
case 'e': case 'e':
flags |= PO_EXPAND; po_exp = true;
break; break;
case 'n': case 'n':
flags &= ~PO_NL; po_nl = false;
break; break;
case 'p': case 'p':
if ((fd = coproc_getfd(W_OK, &emsg)) < 0) { if ((fd = coproc_getfd(W_OK, &emsg)) < 0) {
bi_errorf("%s: %s", "-p", emsg); bi_errorf("-p: %s", emsg);
return (1); return (1);
} }
break; break;
case 'R':
/* fake BSD echo command */
po_pminusminus = true;
po_exp = false;
opts = "en";
break;
case 'r': case 'r':
flags &= ~PO_EXPAND; po_exp = false;
break; break;
case 's': case 's':
flags |= PO_HIST; po_hist = true;
break; break;
case 'u': case 'u':
if (!*(s = builtin_opt.optarg)) if (!*(s = builtin_opt.optarg))
fd = 0; fd = 0;
else if ((fd = check_fd(s, W_OK, &emsg)) < 0) { else if ((fd = check_fd(s, W_OK, &emsg)) < 0) {
bi_errorf("%s: %s: %s", "-u", s, emsg); bi_errorf("-u%s: %s", s, emsg);
return (1); return (1);
} }
break; break;
@ -393,22 +394,23 @@ c_print(const char **wp)
} }
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] &&
ksh_isdash(wp[builtin_opt.optind])) ksh_isdash(wp[builtin_opt.optind]))
builtin_opt.optind++; builtin_opt.optind++;
} else if (flags & PO_PMINUSMINUS) } else if (po_pminusminus)
builtin_opt.optind--; builtin_opt.optind--;
wp += builtin_opt.optind; wp += builtin_opt.optind;
} }
Xinit(xs, xp, 128, ATEMP); Xinit(xs, xp, 128, ATEMP);
while (*wp != NULL) { if (*wp != NULL) {
print_read_arg:
s = *wp; s = *wp;
while ((c = *s++) != '\0') { while ((c = *s++) != '\0') {
Xcheck(xs, xp); Xcheck(xs, xp);
if ((flags & PO_EXPAND) && c == '\\') { if (po_exp && c == '\\') {
s_ptr = s; s_ptr = s;
c = unbksl(false, s_get, s_put); c = unbksl(false, s_get, s_put);
s = s_ptr; s = s_ptr;
@ -416,11 +418,11 @@ c_print(const char **wp)
/* rejected by generic function */ /* rejected by generic function */
switch ((c = *s++)) { switch ((c = *s++)) {
case 'c': case 'c':
flags &= ~PO_NL; po_nl = false;
/* AT&T brain damage */ /* AT&T brain damage */
continue; continue;
case '\0': case '\0':
s--; --s;
c = '\\'; c = '\\';
break; break;
default: default:
@ -440,18 +442,22 @@ c_print(const char **wp)
} }
Xput(xs, xp, c); Xput(xs, xp, c);
} }
if (*++wp != NULL) if (*++wp != NULL) {
Xput(xs, xp, ' '); Xput(xs, xp, ' ');
goto print_read_arg;
} }
if (flags & PO_NL) }
if (po_nl)
Xput(xs, xp, '\n'); Xput(xs, xp, '\n');
if (flags & PO_HIST) { c = 0;
if (po_hist) {
Xput(xs, xp, '\0'); Xput(xs, xp, '\0');
histsave(&source->line, Xstring(xs, xp), HIST_STORE, false); histsave(&source->line, Xstring(xs, xp), HIST_STORE, false);
Xfree(xs, xp); Xfree(xs, xp);
} else { } else {
int len = Xlength(xs, xp); size_t len = Xlength(xs, xp);
bool po_coproc = false;
int opipe = 0; int opipe = 0;
/* /*
@ -461,30 +467,36 @@ c_print(const char **wp)
* not enough). * not enough).
*/ */
if (coproc.write >= 0 && coproc.write == fd) { if (coproc.write >= 0 && coproc.write == fd) {
flags |= PO_COPROC; po_coproc = true;
opipe = block_pipe(); opipe = block_pipe();
} }
for (s = Xstring(xs, xp); len > 0; ) {
if ((c = write(fd, s, len)) < 0) { s = Xstring(xs, xp);
if (flags & PO_COPROC) while (len > 0) {
restore_pipe(opipe); ssize_t nwritten;
if ((nwritten = write(fd, s, len)) < 0) {
if (errno == EINTR) { if (errno == EINTR) {
/* allow user to ^C out */ if (po_coproc)
restore_pipe(opipe);
/* give the user a chance to ^C out */
intrcheck(); intrcheck();
if (flags & PO_COPROC) /* interrupted, try again */
if (po_coproc)
opipe = block_pipe(); opipe = block_pipe();
continue; continue;
} }
return (1); c = 1;
break;
} }
s += c; s += nwritten;
len -= c; len -= nwritten;
} }
if (flags & PO_COPROC) if (po_coproc)
restore_pipe(opipe); restore_pipe(opipe);
} }
return (0); return (c);
} }
static int static int

35
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.217 2016/01/19 23:12:14 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.218 2016/01/20 21:34:12 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -94,8 +94,7 @@ static void ungetsc_i(int);
static int getsc_uu(void); static int getsc_uu(void);
static void getsc_line(Source *); static void getsc_line(Source *);
static int getsc_bn(void); static int getsc_bn(void);
static int s_get(void); static int getsc_i(void);
static void s_put(int);
static char *get_brace_var(XString *, char *); static char *get_brace_var(XString *, char *);
static bool arraysub(char **); static bool arraysub(char **);
static void gethere(void); static void gethere(void);
@ -112,7 +111,7 @@ static int ignore_backslash_newline;
#define o_getsc_u() ((*source->str != '\0') ? *source->str++ : getsc_uu()) #define o_getsc_u() ((*source->str != '\0') ? *source->str++ : getsc_uu())
/* retrace helper */ /* retrace helper */
#define o_getsc_r(carg) { \ #define o_getsc_r(carg) \
int cev = (carg); \ int cev = (carg); \
struct sretrace_info *rp = retrace_info; \ struct sretrace_info *rp = retrace_info; \
\ \
@ -122,17 +121,17 @@ static int ignore_backslash_newline;
rp = rp->next; \ rp = rp->next; \
} \ } \
\ \
return (cev); \ return (cev);
}
#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
static int getsc(void);
/* callback */
static int static int
getsc(void) getsc_i(void)
{ {
o_getsc_r(o_getsc()); o_getsc_r(o_getsc());
} }
#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
#define getsc getsc_i
#else #else
static int getsc_r(int); static int getsc_r(int);
@ -590,8 +589,8 @@ yylex(int cf)
*wp++ = CQUOTE; *wp++ = CQUOTE;
ignore_backslash_newline--; ignore_backslash_newline--;
} else if (c == '\\') { } else if (c == '\\') {
if ((c2 = unbksl(true, s_get, s_put)) == -1) if ((c2 = unbksl(true, getsc_i, ungetsc)) == -1)
c2 = s_get(); c2 = getsc();
if (c2 == 0) if (c2 == 0)
statep->ls_bool = true; statep->ls_bool = true;
if (!statep->ls_bool) { if (!statep->ls_bool) {
@ -1787,15 +1786,3 @@ pop_state_i(State_info *si, Lex_state *old_end)
return (si->base + STATE_BSIZE - 1); return (si->base + STATE_BSIZE - 1);
} }
static int
s_get(void)
{
return (getsc());
}
static void
s_put(int c)
{
ungetsc(c);
}

4
sh.h
View File

@ -175,9 +175,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.756 2016/01/19 23:12:14 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.757 2016/01/20 21:34:13 tg Exp $");
#endif #endif
#define MKSH_VERSION "R52 2016/01/19" #define MKSH_VERSION "R52 2016/01/20"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES