summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 14:56:10 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-09-13 14:56:10 +0900
commitc90fa15cbf2fc4380c58ff1b32f31d9ad6f57f81 (patch)
tree6550151487ff940dc98a5bc77cfd8ab2f1f387b5
parent8d39e6d71933b767be25ad1af9b0e7811b68d887 (diff)
downloaddash-c90fa15cbf2fc4380c58ff1b32f31d9ad6f57f81.tar.gz
dash-c90fa15cbf2fc4380c58ff1b32f31d9ad6f57f81.tar.bz2
dash-c90fa15cbf2fc4380c58ff1b32f31d9ad6f57f81.zip
Imported Upstream version 0.5.9.1upstream/0.5.9.1
Change-Id: I7e95f2313b69beadd45cc22a87e973301c191774 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
-rwxr-xr-xconfigure20
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/Makefile.in4
-rw-r--r--src/bltin/printf.c25
-rw-r--r--src/dash.15
-rw-r--r--src/eval.c140
-rw-r--r--src/eval.h2
-rw-r--r--src/expand.c116
-rw-r--r--src/expand.h2
-rw-r--r--src/jobs.c10
-rw-r--r--src/main.c7
-rw-r--r--src/miscbltin.c30
-rw-r--r--src/mkbuiltins12
-rw-r--r--src/trap.c25
15 files changed, 235 insertions, 169 deletions
diff --git a/configure b/configure
index 3d5a8de..d5da219 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dash 0.5.9.
+# Generated by GNU Autoconf 2.69 for dash 0.5.9.1.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='dash'
PACKAGE_TARNAME='dash'
-PACKAGE_VERSION='0.5.9'
-PACKAGE_STRING='dash 0.5.9'
+PACKAGE_VERSION='0.5.9.1'
+PACKAGE_STRING='dash 0.5.9.1'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1269,7 +1269,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures dash 0.5.9 to adapt to many kinds of systems.
+\`configure' configures dash 0.5.9.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1335,7 +1335,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of dash 0.5.9:";;
+ short | recursive ) echo "Configuration of dash 0.5.9.1:";;
esac
cat <<\_ACEOF
@@ -1440,7 +1440,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-dash configure 0.5.9
+dash configure 0.5.9.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2034,7 +2034,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by dash $as_me 0.5.9, which was
+It was created by dash $as_me 0.5.9.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2849,7 +2849,7 @@ fi
# Define the identity of the package.
PACKAGE='dash'
- VERSION='0.5.9'
+ VERSION='0.5.9.1'
cat >>confdefs.h <<_ACEOF
@@ -5313,7 +5313,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by dash $as_me 0.5.9, which was
+This file was extended by dash $as_me 0.5.9.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -5379,7 +5379,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-dash config.status 0.5.9
+dash config.status 0.5.9.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 4c2c179..9c4ced8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(dash, 0.5.9)
+AC_INIT(dash, 0.5.9.1)
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_SRCDIR([src/main.c])
diff --git a/src/Makefile.am b/src/Makefile.am
index 120ffa2..139355e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,13 +46,13 @@ EXTRA_DIST = \
mknodes.c nodetypes nodes.c.pat mksyntax.c mksignames.c
token.h token_vars.h: mktokens
- sh $^
+ $(SHELL) $^
builtins.def: builtins.def.in $(top_builddir)/config.h
$(COMPILE) -E -x c -o $@ $<
builtins.c builtins.h: mkbuiltins builtins.def
- sh $^
+ $(SHELL) $^
init.c: mkinit $(dash_CFILES)
./$^
diff --git a/src/Makefile.in b/src/Makefile.in
index 4ccb12c..0bd9ad1 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -691,13 +691,13 @@ uninstall-man: uninstall-man1
token.h token_vars.h: mktokens
- sh $^
+ $(SHELL) $^
builtins.def: builtins.def.in $(top_builddir)/config.h
$(COMPILE) -E -x c -o $@ $<
builtins.c builtins.h: mkbuiltins builtins.def
- sh $^
+ $(SHELL) $^
init.c: mkinit $(dash_CFILES)
./$^
diff --git a/src/bltin/printf.c b/src/bltin/printf.c
index 9673e10..a626cee 100644
--- a/src/bltin/printf.c
+++ b/src/bltin/printf.c
@@ -175,17 +175,24 @@ pc:
/* skip to field width */
fmt += strspn(fmt, SKIP1);
- if (*fmt == '*')
- *param++ = getuintmax(1);
-
- /* skip to possible '.', get following precision */
- fmt += strspn(fmt, SKIP2);
- if (*fmt == '.')
+ if (*fmt == '*') {
++fmt;
- if (*fmt == '*')
*param++ = getuintmax(1);
+ } else {
+ /* skip to possible '.',
+ * get following precision
+ */
+ fmt += strspn(fmt, SKIP2);
+ }
- fmt += strspn(fmt, SKIP2);
+ if (*fmt == '.') {
+ ++fmt;
+ if (*fmt == '*') {
+ ++fmt;
+ *param++ = getuintmax(1);
+ } else
+ fmt += strspn(fmt, SKIP2);
+ }
ch = *fmt;
if (!ch)
@@ -452,7 +459,7 @@ echocmd(int argc, char **argv)
if (likely(*argv))
nonl += print_escape_str("%s", NULL, NULL, *argv++);
- if (nonl > 0)
+ if (likely((nonl + !*argv) > 1))
break;
c = *argv ? ' ' : '\n';
diff --git a/src/dash.1 b/src/dash.1
index 832eae7..8b8026d 100644
--- a/src/dash.1
+++ b/src/dash.1
@@ -2114,7 +2114,7 @@ printed; for commands and tracked aliases the complete pathname of the
command is printed.
.It ulimit Xo
.Op Fl H \*(Ba Fl S
-.Op Fl a \*(Ba Fl tfdscmlpn Op Ar value
+.Op Fl a \*(Ba Fl tfdscmlpnv Op Ar value
.Xc
Inquire about or set the hard or soft limits on processes or set new
limits.
@@ -2164,6 +2164,9 @@ show or set the limit on the number of processes this user can
have at one time
.It Fl n
show or set the limit on the number files a process can have open at once
+.It Fl v
+show or set the limit on the total virtual memory that can be
+in use by a process (in kilobytes)
.It Fl r
show or set the limit on the real-time scheduling priority of a process
.El
diff --git a/src/eval.c b/src/eval.c
index 071fb1b..7498f9d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -81,16 +81,16 @@ int savestatus = -1; /* exit status of last command outside traps */
STATIC
#endif
void evaltreenr(union node *, int) __attribute__ ((__noreturn__));
-STATIC void evalloop(union node *, int);
-STATIC void evalfor(union node *, int);
-STATIC void evalcase(union node *, int);
-STATIC void evalsubshell(union node *, int);
+STATIC int evalloop(union node *, int);
+STATIC int evalfor(union node *, int);
+STATIC int evalcase(union node *, int);
+STATIC int evalsubshell(union node *, int);
STATIC void expredir(union node *);
-STATIC void evalpipe(union node *, int);
+STATIC int evalpipe(union node *, int);
#ifdef notyet
-STATIC void evalcommand(union node *, int, struct backcmd *);
+STATIC int evalcommand(union node *, int, struct backcmd *);
#else
-STATIC void evalcommand(union node *, int);
+STATIC int evalcommand(union node *, int);
#endif
STATIC int evalbltin(const struct builtincmd *, int, char **, int);
STATIC int evalfun(struct funcnode *, int, char **, int);
@@ -170,10 +170,13 @@ evalstring(char *s, int flags)
setstackmark(&smark);
status = 0;
- while ((n = parsecmd(0)) != NEOF) {
- evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
- status = exitstatus;
- popstackmark(&smark);
+ for (; (n = parsecmd(0)) != NEOF; popstackmark(&smark)) {
+ int i;
+
+ i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
+ if (n)
+ status = i;
+
if (evalskip)
break;
}
@@ -191,13 +194,13 @@ evalstring(char *s, int flags)
* exitstatus.
*/
-void
+int
evaltree(union node *n, int flags)
{
int checkexit = 0;
- void (*evalfn)(union node *, int);
+ int (*evalfn)(union node *, int);
unsigned isor;
- int status;
+ int status = 0;
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
goto out;
@@ -220,8 +223,7 @@ evaltree(union node *n, int flags)
break;
#endif
case NNOT:
- evaltree(n->nnot.com, EV_TESTED);
- status = !exitstatus;
+ status = !evaltree(n->nnot.com, EV_TESTED);
goto setstatus;
case NREDIR:
errlinno = lineno = n->nredir.linno;
@@ -229,11 +231,8 @@ evaltree(union node *n, int flags)
lineno -= funcline - 1;
expredir(n->nredir.redirect);
pushredir(n->nredir.redirect);
- status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
- if (!status) {
- evaltree(n->nredir.n, flags & EV_TESTED);
- status = exitstatus;
- }
+ status = redirectsafe(n->nredir.redirect, REDIR_PUSH) ?:
+ evaltree(n->nredir.n, flags & EV_TESTED);
if (n->nredir.redirect)
popredir(0);
goto setstatus;
@@ -241,8 +240,8 @@ evaltree(union node *n, int flags)
#ifdef notyet
if (eflag && !(flags & EV_TESTED))
checkexit = ~0;
- evalcommand(n, flags, (struct backcmd *)NULL);
- break;
+ status = evalcommand(n, flags, (struct backcmd *)NULL);
+ goto setstatus;
#else
evalfn = evalcommand;
checkexit:
@@ -277,43 +276,37 @@ checkexit:
#error NOR + 1 != NSEMI
#endif
isor = n->type - NAND;
- evaltree(
- n->nbinary.ch1,
- (flags | ((isor >> 1) - 1)) & EV_TESTED
- );
- if (!exitstatus == isor)
+ status = evaltree(n->nbinary.ch1,
+ (flags | ((isor >> 1) - 1)) & EV_TESTED);
+ if (!status == isor || evalskip)
break;
- if (!evalskip) {
- n = n->nbinary.ch2;
+ n = n->nbinary.ch2;
evaln:
- evalfn = evaltree;
+ evalfn = evaltree;
calleval:
- evalfn(n, flags);
- break;
- }
- break;
+ status = evalfn(n, flags);
+ goto setstatus;
case NIF:
- evaltree(n->nif.test, EV_TESTED);
+ status = evaltree(n->nif.test, EV_TESTED);
if (evalskip)
break;
- if (exitstatus == 0) {
+ if (!status) {
n = n->nif.ifpart;
goto evaln;
} else if (n->nif.elsepart) {
n = n->nif.elsepart;
goto evaln;
}
- goto success;
+ status = 0;
+ goto setstatus;
case NDEFUN:
defun(n);
-success:
- status = 0;
setstatus:
exitstatus = status;
break;
}
out:
- if (checkexit & exitstatus)
+ if (checkexit & status)
goto exexit;
dotrap();
@@ -322,6 +315,8 @@ out:
exexit:
exraise(EXEXIT);
}
+
+ return exitstatus;
}
@@ -362,7 +357,7 @@ static int skiploop(void)
}
-STATIC void
+STATIC int
evalloop(union node *n, int flags)
{
int skip;
@@ -374,33 +369,34 @@ evalloop(union node *n, int flags)
do {
int i;
- evaltree(n->nbinary.ch1, EV_TESTED);
+ i = evaltree(n->nbinary.ch1, EV_TESTED);
skip = skiploop();
+ if (skip == SKIPFUNC)
+ status = i;
if (skip)
continue;
- i = exitstatus;
if (n->type != NWHILE)
i = !i;
if (i != 0)
break;
- evaltree(n->nbinary.ch2, flags);
- status = exitstatus;
+ status = evaltree(n->nbinary.ch2, flags);
skip = skiploop();
} while (!(skip & ~SKIPCONT));
- if (skip != SKIPFUNC)
- exitstatus = status;
loopnest--;
+
+ return status;
}
-STATIC void
+STATIC int
evalfor(union node *n, int flags)
{
struct arglist arglist;
union node *argp;
struct strlist *sp;
struct stackmark smark;
+ int status;
errlinno = lineno = n->nfor.linno;
if (funcline)
@@ -413,28 +409,31 @@ evalfor(union node *n, int flags)
}
*arglist.lastp = NULL;
- exitstatus = 0;
+ status = 0;
loopnest++;
flags &= EV_TESTED;
for (sp = arglist.list ; sp ; sp = sp->next) {
setvar(n->nfor.var, sp->text, 0);
- evaltree(n->nfor.body, flags);
+ status = evaltree(n->nfor.body, flags);
if (skiploop() & ~SKIPCONT)
break;
}
loopnest--;
popstackmark(&smark);
+
+ return status;
}
-STATIC void
+STATIC int
evalcase(union node *n, int flags)
{
union node *cp;
union node *patp;
struct arglist arglist;
struct stackmark smark;
+ int status = 0;
errlinno = lineno = n->ncase.linno;
if (funcline)
@@ -443,12 +442,16 @@ evalcase(union node *n, int flags)
setstackmark(&smark);
arglist.lastp = &arglist.list;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
- exitstatus = 0;
for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
- if (evalskip == 0) {
- evaltree(cp->nclist.body, flags);
+ /* Ensure body is non-empty as otherwise
+ * EV_EXIT may prevent us from setting the
+ * exit status.
+ */
+ if (evalskip == 0 && cp->nclist.body) {
+ status = evaltree(cp->nclist.body,
+ flags);
}
goto out;
}
@@ -456,6 +459,8 @@ evalcase(union node *n, int flags)
}
out:
popstackmark(&smark);
+
+ return status;
}
@@ -464,7 +469,7 @@ out:
* Kick off a subshell to evaluate a tree.
*/
-STATIC void
+STATIC int
evalsubshell(union node *n, int flags)
{
struct job *jp;
@@ -493,8 +498,8 @@ nofork:
status = 0;
if (! backgnd)
status = waitforjob(jp);
- exitstatus = status;
INTON;
+ return status;
}
@@ -540,7 +545,7 @@ expredir(union node *n)
* of all the rest.)
*/
-STATIC void
+STATIC int
evalpipe(union node *n, int flags)
{
struct job *jp;
@@ -548,6 +553,7 @@ evalpipe(union node *n, int flags)
int pipelen;
int prevfd;
int pip[2];
+ int status = 0;
TRACE(("evalpipe(0x%lx) called\n", (long)n));
pipelen = 0;
@@ -588,10 +594,12 @@ evalpipe(union node *n, int flags)
close(pip[1]);
}
if (n->npipe.backgnd == 0) {
- exitstatus = waitforjob(jp);
- TRACE(("evalpipe: job done exit status %d\n", exitstatus));
+ status = waitforjob(jp);
+ TRACE(("evalpipe: job done exit status %d\n", status));
}
INTON;
+
+ return status;
}
@@ -678,7 +686,7 @@ parse_command_args(char **argv, const char **path)
* Execute a simple command.
*/
-STATIC void
+STATIC int
#ifdef notyet
evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
#else
@@ -848,7 +856,7 @@ bail:
INTOFF;
jp = makejob(cmd, 1);
if (forkshell(jp, cmd, FORK_FG) != 0) {
- exitstatus = waitforjob(jp);
+ status = waitforjob(jp);
INTON;
break;
}
@@ -867,17 +875,19 @@ bail:
if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
if (exception == EXERROR && spclbltin <= 0) {
FORCEINTON;
- break;
+ goto readstatus;
}
raise:
longjmp(handler->loc, 1);
}
- break;
+ goto readstatus;
case CMDFUNCTION:
poplocalvars(1);
if (evalfun(cmdentry.u.func, argc, argv, flags))
goto raise;
+readstatus:
+ status = exitstatus;
break;
}
@@ -893,6 +903,8 @@ out:
*/
setvar("_", lastarg, 0);
popstackmark(&smark);
+
+ return status;
}
STATIC int
diff --git a/src/eval.h b/src/eval.h
index 6e8acda..63e7d86 100644
--- a/src/eval.h
+++ b/src/eval.h
@@ -53,7 +53,7 @@ struct backcmd { /* result of evalbackcmd */
int evalstring(char *, int);
union node; /* BLETCH for ansi C */
-void evaltree(union node *, int);
+int evaltree(union node *, int);
void evalbackcmd(union node *, struct backcmd *);
extern int evalskip;
diff --git a/src/expand.c b/src/expand.c
index b2d710d..2a50830 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -50,6 +50,7 @@
#include <glob.h>
#endif
#include <ctype.h>
+#include <stdbool.h>
/*
* Routines to expand arguments to commands. We have to deal with
@@ -203,7 +204,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
* TODO - EXP_REDIR
*/
if (flag & EXP_FULL) {
- ifsbreakup(p, &exparg);
+ ifsbreakup(p, -1, &exparg);
*exparg.lastp = NULL;
exparg.lastp = &exparg.list;
expandmeta(exparg.list, flag);
@@ -1016,15 +1017,18 @@ recordregion(int start, int end, int nulonly)
* Break the argument string into pieces based upon IFS and add the
* strings to the argument list. The regions of the string to be
* searched for IFS characters have been stored by recordregion.
+ * If maxargs is non-negative, at most maxargs arguments will be created, by
+ * joining together the last arguments.
*/
void
-ifsbreakup(char *string, struct arglist *arglist)
+ifsbreakup(char *string, int maxargs, struct arglist *arglist)
{
struct ifsregion *ifsp;
struct strlist *sp;
char *start;
char *p;
char *q;
+ char *r = NULL;
const char *ifs, *realifs;
int ifsspc;
int nulonly;
@@ -1042,16 +1046,76 @@ ifsbreakup(char *string, struct arglist *arglist)
ifs = nulonly ? nullstr : realifs;
ifsspc = 0;
while (p < string + ifsp->endoff) {
+ int c;
+ bool isifs;
+ bool isdefifs;
+
q = p;
- if (*p == (char)CTLESC)
- p++;
- if (strchr(ifs, *p)) {
+ c = *p++;
+ if (c == (char)CTLESC)
+ c = *p++;
+
+ isifs = strchr(ifs, c);
+ isdefifs = false;
+ if (isifs)
+ isdefifs = strchr(defifs, c);
+
+ /* If only reading one more argument:
+ * If we have exactly one field,
+ * read that field without its terminator.
+ * If we have more than one field,
+ * read all fields including their terminators,
+ * except for trailing IFS whitespace.
+ *
+ * This means that if we have only IFS
+ * characters left, and at most one
+ * of them is non-whitespace, we stop
+ * reading here.
+ * Otherwise, we read all the remaining
+ * characters except for trailing
+ * IFS whitespace.
+ *
+ * In any case, r indicates the start
+ * of the characters to remove, or NULL
+ * if no characters should be removed.
+ */
+ if (!maxargs) {
+ if (isdefifs) {
+ if (!r)
+ r = q;
+ continue;
+ }
+
+ if (!(isifs && ifsspc))
+ r = NULL;
+
+ ifsspc = 0;
+ continue;
+ }
+
+ if (ifsspc) {
+ if (isifs)
+ q = p;
+
+ start = q;
+
+ if (isdefifs)
+ continue;
+
+ isifs = false;
+ }
+
+ if (isifs) {
if (!nulonly)
- ifsspc = (strchr(defifs, *p) != NULL);
+ ifsspc = isdefifs;
/* Ignore IFS whitespace at start */
if (q == start && ifsspc) {
- p++;
start = p;
+ ifsspc = 0;
+ continue;
+ }
+ if (maxargs > 0 && !--maxargs) {
+ r = q;
continue;
}
*q = '\0';
@@ -1059,39 +1123,20 @@ ifsbreakup(char *string, struct arglist *arglist)
sp->text = start;
*arglist->lastp = sp;
arglist->lastp = &sp->next;
- p++;
- if (!nulonly) {
- for (;;) {
- if (p >= string + ifsp->endoff) {
- break;
- }
- q = p;
- if (*p == (char)CTLESC)
- p++;
- if (strchr(ifs, *p) == NULL ) {
- p = q;
- break;
- } else if (strchr(defifs, *p) == NULL) {
- if (ifsspc) {
- p++;
- ifsspc = 0;
- } else {
- p = q;
- break;
- }
- } else
- p++;
- }
- }
start = p;
- } else
- p++;
+ continue;
+ }
+
+ ifsspc = 0;
}
} while ((ifsp = ifsp->next) != NULL);
if (nulonly)
goto add;
}
+ if (r)
+ *r = '\0';
+
if (!*start)
return;
@@ -1539,14 +1584,14 @@ pmatch(const char *pattern, const char *string)
p++;
}
found = 0;
- chr = *q++;
+ chr = *q;
if (chr == '\0')
return 0;
c = *p++;
do {
if (!c) {
p = startp;
- c = *p;
+ c = '[';
goto dft;
}
if (c == '[') {
@@ -1573,6 +1618,7 @@ pmatch(const char *pattern, const char *string)
} while ((c = *p++) != ']');
if (found == invert)
return 0;
+ q++;
break;
}
dft: default:
diff --git a/src/expand.h b/src/expand.h
index 6a90f67..26dc5b4 100644
--- a/src/expand.h
+++ b/src/expand.h
@@ -69,7 +69,7 @@ char *_rmescapes(char *, int);
int casematch(union node *, char *);
void recordregion(int, int, int);
void removerecordregions(int);
-void ifsbreakup(char *, struct arglist *);
+void ifsbreakup(char *, int, struct arglist *);
void ifsfree(void);
/* From arith.y */
diff --git a/src/jobs.c b/src/jobs.c
index c2c2332..4f02e38 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -699,7 +699,7 @@ check:
if (is_number(p)) {
num = atoi(p);
- if (num <= njobs) {
+ if (num > 0 && num <= njobs) {
jp = jobtab + num - 1;
if (jp->used)
goto gotit;
@@ -714,9 +714,7 @@ check:
}
found = 0;
- while (1) {
- if (!jp)
- goto err;
+ while (jp) {
if (match(jp->ps[0].cmd, p)) {
if (found)
goto err;
@@ -726,6 +724,10 @@ check:
jp = jp->prev_job;
}
+ if (!found)
+ goto err;
+ jp = found;
+
gotit:
#if JOBS
err_msg = "job %s not created under job control";
diff --git a/src/main.c b/src/main.c
index bedb663..fcd3e7d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -225,10 +225,13 @@ cmdloop(int top)
}
numeof++;
} else if (nflag == 0) {
+ int i;
+
job_warning = (job_warning == 2) ? 1 : 0;
numeof = 0;
- evaltree(n, 0);
- status = exitstatus;
+ i = evaltree(n, 0);
+ if (n)
+ status = i;
}
popstackmark(&smark);
diff --git a/src/miscbltin.c b/src/miscbltin.c
index b596fd2..39b9c47 100644
--- a/src/miscbltin.c
+++ b/src/miscbltin.c
@@ -67,28 +67,21 @@
* less fields than variables -> remaining variables unset.
*
* @param line complete line of input
+ * @param ac argument count
* @param ap argument (variable) list
* @param len length of line including trailing '\0'
*/
static void
-readcmd_handle_line(char *s, char **ap)
+readcmd_handle_line(char *s, int ac, char **ap)
{
struct arglist arglist;
struct strlist *sl;
- char *backup;
- char *line;
- /* ifsbreakup will fiddle with stack region... */
- line = stackblock();
s = grabstackstr(s);
- /* need a copy, so that delimiters aren't lost
- * in case there are more fields than variables */
- backup = sstrdup(line);
-
arglist.lastp = &arglist.list;
- ifsbreakup(s, &arglist);
+ ifsbreakup(s, ac, &arglist);
*arglist.lastp = NULL;
ifsfree();
@@ -104,21 +97,6 @@ readcmd_handle_line(char *s, char **ap)
return;
}
- /* remaining fields present, but no variables left. */
- if (!ap[1] && sl->next) {
- size_t offset;
- char *remainder;
-
- /* FIXME little bit hacky, assuming that ifsbreakup
- * will not modify the length of the string */
- offset = sl->text - s;
- remainder = backup + offset;
- rmescapes(remainder);
- setvar(*ap, remainder, 0);
-
- return;
- }
-
/* set variable to field */
rmescapes(sl->text);
setvar(*ap, sl->text, 0);
@@ -211,7 +189,7 @@ start:
out:
recordregion(startloc, p - (char *)stackblock(), 0);
STACKSTRNUL(p);
- readcmd_handle_line(p + 1, ap);
+ readcmd_handle_line(p + 1, argc - (ap - argv), ap);
return status;
}
diff --git a/src/mkbuiltins b/src/mkbuiltins
index 8c74d6b..b4d6f4e 100644
--- a/src/mkbuiltins
+++ b/src/mkbuiltins
@@ -84,9 +84,13 @@ awk '{ for (i = 2 ; i <= NF ; i++) {
opt = substr($2, 2)
$2 = $3
}
- printf "\t{ \"%s\", %s, %d },\n", $1,
- (opt ~ /n/) ? "NULL" : $2,
- (opt ~ /s/) + (opt ~ /[su]/) * 2 + (opt ~ /a/) * 4
+ mask = 0
+ cmd = $2
+ if (opt ~ /n/) { cmd = "NULL" }
+ if (opt ~ /s/) { mask += 1 }
+ if (opt ~ /[su]/) { mask += 2 }
+ if (opt ~ /a/) { mask += 4 }
+ printf "\t{ \"%s\", %s, %d },\n", $1, cmd, mask
}'
echo '};'
@@ -97,7 +101,7 @@ cat <<\!
*/
!
-sed 's/ -[a-z]*//' $temp2 | nl -b a -v 0 |
+sed 's/ -[a-z]*//' $temp2 | nl -ba -v0 |
LC_ALL= LC_COLLATE=C sort -u -k 3,3 |
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ |
awk '{ printf "#define %s (builtincmd + %d)\n", $3, $1}'
diff --git a/src/trap.c b/src/trap.c
index 82d4263..edb9938 100644
--- a/src/trap.c
+++ b/src/trap.c
@@ -79,6 +79,8 @@ int gotsigchld;
extern char *signal_names[];
+static int decode_signum(const char *);
+
#ifdef mkinit
INCLUDE "trap.h"
INIT {
@@ -112,7 +114,7 @@ trapcmd(int argc, char **argv)
}
return 0;
}
- if (!ap[1])
+ if (!ap[1] || decode_signum(*ap) >= 0)
action = NULL;
else
action = *ap++;
@@ -400,18 +402,27 @@ out:
/* NOTREACHED */
}
-int decode_signal(const char *string, int minsig)
+static int decode_signum(const char *string)
{
- int signo;
+ int signo = -1;
if (is_number(string)) {
signo = atoi(string);
- if (signo >= NSIG) {
- return -1;
- }
- return signo;
+ if (signo >= NSIG)
+ signo = -1;
}
+ return signo;
+}
+
+int decode_signal(const char *string, int minsig)
+{
+ int signo;
+
+ signo = decode_signum(string);
+ if (signo >= 0)
+ return signo;
+
for (signo = minsig; signo < NSIG; signo++) {
if (!strcasecmp(string, signal_names[signo])) {
return signo;