fix errno in print/echo builtin; optimise (with partial rewrite)
This commit is contained in:
parent
9167be0584
commit
61f7661b92
6
check.t
6
check.t
@ -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
162
funcs.c
@ -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
35
lex.c
@ -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
4
sh.h
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user