From 996e05548ab82f7ef2dea61f109cc7b6d13837fa Mon Sep 17 00:00:00 2001 From: tg Date: Sun, 12 Oct 2014 21:58:53 +0000 Subject: [PATCH] =?UTF-8?q?POSIX=20says=20=E2=80=9Ccommand=E2=80=9D=20lose?= =?UTF-8?q?s=20SPEC=5FBI=20and=20means=20it=20too?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reported by ormaaj, who even asked on the austin ML http://thread.gmane.org/gmane.comp.standards.posix.austin.general/9907/focus=9931 clarified by jilles; also make errorlevels match ksh93 --- exec.c | 29 +++++++++++++++-------------- funcs.c | 21 ++++++++++++--------- main.c | 4 ++-- sh.h | 6 +++--- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/exec.c b/exec.c index 6cffd00..eb89b00 100644 --- a/exec.c +++ b/exec.c @@ -23,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.135 2014/10/12 20:32:09 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.136 2014/10/12 21:58:50 tg Exp $"); #ifndef MKSH_DEFAULT_EXECSHELL #define MKSH_DEFAULT_EXECSHELL "/bin/sh" @@ -32,7 +32,7 @@ __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.135 2014/10/12 20:32:09 tg Exp $"); static int comexec(struct op *, struct tbl * volatile, const char **, int volatile, volatile int *); static void scriptexec(struct op *, const char **) MKSH_A_NORETURN; -static int call_builtin(struct tbl *, const char **, const char *); +static int call_builtin(struct tbl *, const char **, const char *, bool); static int iosetup(struct ioword *, struct tbl *); static int herein(struct ioword *, char **); static const char *do_selectargs(const char **, bool); @@ -505,7 +505,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, /* Must be static (XXX but why?) */ static struct op texec; int type_flags; - bool keepasn_ok; + bool resetspec; int fcflags = FC_BI|FC_FUNC|FC_PATH; bool bourne_function_call = false; struct block *l_expand, *l_assign; @@ -537,7 +537,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, * FOO=bar command FOO is neither kept nor exported * PATH=... foobar use new PATH in foobar search */ - keepasn_ok = true; + resetspec = false; while (tp && tp->type == CSHELL) { /* undo effects of command */ fcflags = FC_BI|FC_FUNC|FC_PATH; @@ -584,7 +584,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, * POSIX says special builtins lose their status * if accessed using command. */ - keepasn_ok = false; + resetspec = true; if (!ap[0]) { /* ensure command with no args exits with 0 */ subst_exstat = 0; @@ -619,13 +619,13 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, if (t->u.evalflags & DOTCOMEXEC) flags |= XEXEC; l_expand = e->loc; - if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN)))) + if (!resetspec && (!ap[0] || (tp && (tp->flag & KEEPASN)))) type_flags = 0; else { /* create new variable/function block */ newblock(); /* ksh functions don't keep assignments, POSIX functions do. */ - if (keepasn_ok && tp && tp->type == CFUNC && + if (!resetspec && tp && tp->type == CFUNC && !(tp->flag & FKSH)) { bourne_function_call = true; type_flags = EXPORT; @@ -689,8 +689,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap, /* shell built-in */ case CSHELL: - rv = call_builtin(tp, (const char **)ap, null); - if (!keepasn_ok && tp->val.f == c_shift) { + rv = call_builtin(tp, (const char **)ap, null, resetspec); + if (resetspec && tp->val.f == c_shift) { l_expand->argc = l_assign->argc; l_expand->argv = l_assign->argv; } @@ -957,7 +957,7 @@ shcomexec(const char **wp) struct tbl *tp; tp = ktsearch(&builtins, *wp, hash(*wp)); - return (call_builtin(tp, wp, "shcomexec")); + return (call_builtin(tp, wp, "shcomexec", false)); } /* @@ -1270,22 +1270,22 @@ search_path(const char *name, const char *lpath, } static int -call_builtin(struct tbl *tp, const char **wp, const char *where) +call_builtin(struct tbl *tp, const char **wp, const char *where, bool resetspec) { int rv; if (!tp) internal_errorf("%s: %s", where, wp[0]); builtin_argv0 = wp[0]; - builtin_flag = tp->flag; + builtin_spec = tobool(!resetspec && (tp->flag & SPEC_BI)); shf_reopen(1, SHF_WR, shl_stdout); shl_stdout_ok = true; ksh_getopt_reset(&builtin_opt, GF_ERROR); rv = (*tp->val.f)(wp); shf_flush(shl_stdout); shl_stdout_ok = false; - builtin_flag = 0; builtin_argv0 = NULL; + builtin_spec = false; return (rv); } @@ -1564,7 +1564,8 @@ do_selectargs(const char **ap, bool print_menu) if (print_menu || !*str_val(global("REPLY"))) pr_menu(ap); shellf("%s", str_val(global("PS3"))); - if (call_builtin(findcom("read", FC_BI), read_args, Tselect)) + if (call_builtin(findcom("read", FC_BI), read_args, Tselect, + false)) return (NULL); s = str_val(global("REPLY")); if (*s && getn(s, &i)) diff --git a/funcs.c b/funcs.c index bb7971e..db3eabf 100644 --- a/funcs.c +++ b/funcs.c @@ -38,7 +38,7 @@ #endif #endif -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.258 2014/09/03 19:55:51 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.259 2014/10/12 21:58:51 tg Exp $"); #if HAVE_KILLPG /* @@ -1587,12 +1587,16 @@ c_shift(const char **wp) return (1); arg = wp[builtin_opt.optind]; - if (arg) { - evaluate(arg, &val, KSH_UNWIND_ERROR, false); - n = val; - } else + if (!arg) n = 1; - if (n < 0) { + else if (!evaluate(arg, &val, KSH_RETURN_ERROR, false)) { + /* error already printed */ + bi_errorfz(); + return (1); + } else if (!(n = val)) { + /* nothing to do */ + return (0); + } else if (n < 0) { bi_errorf("%s: %s", arg, "bad number"); return (1); } @@ -2417,9 +2421,8 @@ c_set(const char **wp) return (c_typeset(args)); } - argi = parse_args(wp, OF_SET, &setargs); - if (argi < 0) - return (1); + if ((argi = parse_args(wp, OF_SET, &setargs)) < 0) + return (2); /* set $# and $* */ if (setargs) { wp += argi - 1; diff --git a/main.c b/main.c index f12d9b9..3d659ca 100644 --- a/main.c +++ b/main.c @@ -34,7 +34,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.284 2014/10/03 17:19:27 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.285 2014/10/12 21:58:52 tg Exp $"); extern char **environ; @@ -1244,7 +1244,7 @@ bi_errorf(const char *fmt, ...) * non-interactive shells to exit. * XXX odd use of KEEPASN; also may not want LERROR here */ - if (builtin_flag & SPEC_BI) { + if (builtin_spec) { builtin_argv0 = NULL; unwind(LERROR); } diff --git a/sh.h b/sh.h index b46cc46..514f54b 100644 --- a/sh.h +++ b/sh.h @@ -169,7 +169,7 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.698 2014/10/12 19:55:01 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.699 2014/10/12 21:58:53 tg Exp $"); #endif #define MKSH_VERSION "R50 2014/10/12" @@ -992,8 +992,8 @@ EXTERN sigset_t sm_default, sm_sigchld; /* name of called builtin function (used by error functions) */ EXTERN const char *builtin_argv0; -/* flags of called builtin (SPEC_BI, etc.) */ -EXTERN uint32_t builtin_flag; +/* is called builtin SPEC_BI? */ +EXTERN bool builtin_spec; /* current working directory */ EXTERN char *current_wd;