summaryrefslogtreecommitdiffstats
path: root/bin/sh
diff options
context:
space:
mode:
authorjimharris <jimharris@FreeBSD.org>2012-01-26 15:23:45 +0000
committerjimharris <jimharris@FreeBSD.org>2012-01-26 15:23:45 +0000
commitbcd0e15cf642d6e5bf78ee585ad282b0e3061864 (patch)
tree4b7b6096856cdeb36fcba0adf3f4d121a52cce21 /bin/sh
parent0cf3f853641c2ededc243c9f2139ac6a0b681fe4 (diff)
parenta479ceccdf3646c7bc3ff60796c765650b3ffc03 (diff)
downloadFreeBSD-src-bcd0e15cf642d6e5bf78ee585ad282b0e3061864.zip
FreeBSD-src-bcd0e15cf642d6e5bf78ee585ad282b0e3061864.tar.gz
Rebase user/jimharris/isci branch from head.
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/arith_yacc.c3
-rw-r--r--bin/sh/arith_yylex.c2
-rw-r--r--bin/sh/cd.c7
-rw-r--r--bin/sh/eval.c47
-rw-r--r--bin/sh/eval.h1
-rw-r--r--bin/sh/exec.c5
-rw-r--r--bin/sh/exec.h1
-rw-r--r--bin/sh/expand.c116
-rw-r--r--bin/sh/expand.h1
-rw-r--r--bin/sh/funcs/kill49
-rw-r--r--bin/sh/histedit.c9
-rw-r--r--bin/sh/input.c15
-rw-r--r--bin/sh/input.h1
-rw-r--r--bin/sh/jobs.c1
-rw-r--r--bin/sh/main.c3
-rw-r--r--bin/sh/main.h1
-rw-r--r--bin/sh/mksyntax.c8
-rw-r--r--bin/sh/myhistedit.h2
-rw-r--r--bin/sh/mystring.c19
-rw-r--r--bin/sh/mystring.h1
-rw-r--r--bin/sh/trap.c37
21 files changed, 172 insertions, 157 deletions
diff --git a/bin/sh/arith_yacc.c b/bin/sh/arith_yacc.c
index 48c63ea..fbf9a64 100644
--- a/bin/sh/arith_yacc.c
+++ b/bin/sh/arith_yacc.c
@@ -84,6 +84,8 @@ static const char prec[ARITH_BINOP_MAX - ARITH_BINOP_MIN] = {
#define ARITH_MAX_PREC 8
+int letcmd(int, char **);
+
static __dead2 void yyerror(const char *s)
{
error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
@@ -377,4 +379,3 @@ letcmd(int argc, char **argv)
out1fmt(ARITH_FORMAT_STR "\n", i);
return !i;
}
-
diff --git a/bin/sh/arith_yylex.c b/bin/sh/arith_yylex.c
index cfb9724d..f6eebdb 100644
--- a/bin/sh/arith_yylex.c
+++ b/bin/sh/arith_yylex.c
@@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$");
extern const char *arith_buf;
int
-yylex()
+yylex(void)
{
int value;
const char *buf = arith_buf;
diff --git a/bin/sh/cd.c b/bin/sh/cd.c
index 6fb1039..1330c85 100644
--- a/bin/sh/cd.c
+++ b/bin/sh/cd.c
@@ -130,7 +130,12 @@ cdcmd(int argc, char **argv)
(path = bltinlookup("CDPATH", 1)) == NULL)
path = nullstr;
while ((p = padvance(&path, dest)) != NULL) {
- if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
+ if (stat(p, &statb) < 0) {
+ if (errno != ENOENT)
+ errno1 = errno;
+ } else if (!S_ISDIR(statb.st_mode))
+ errno1 = ENOTDIR;
+ else {
if (!print) {
/*
* XXX - rethink
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 5e42f79..a5f0aff 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -75,7 +75,7 @@ __FBSDID("$FreeBSD$");
int evalskip; /* set if we are skipping commands */
-static int skipcount; /* number of levels to skip */
+int skipcount; /* number of levels to skip */
MKINIT int loopnest; /* current loop nesting level */
int funcnest; /* depth of function calls */
static int builtin_flags; /* evalcommand flags for builtins */
@@ -89,7 +89,7 @@ int oexitstatus; /* saved exit status */
static void evalloop(union node *, int);
static void evalfor(union node *, int);
-static union node *evalcase(union node *, int);
+static union node *evalcase(union node *);
static void evalsubshell(union node *, int);
static void evalredir(union node *, int);
static void expredir(union node *);
@@ -256,7 +256,18 @@ evaltree(union node *n, int flags)
evalfor(n, flags & ~EV_EXIT);
break;
case NCASE:
- next = evalcase(n, flags);
+ next = evalcase(n);
+ break;
+ case NCLIST:
+ next = n->nclist.body;
+ break;
+ case NCLISTFALLTHRU:
+ if (n->nclist.body) {
+ evaltree(n->nclist.body, flags & ~EV_EXIT);
+ if (evalskip)
+ goto out;
+ }
+ next = n->nclist.next;
break;
case NDEFUN:
defun(n->narg.text, n->narg.next);
@@ -337,6 +348,7 @@ evalfor(union node *n, int flags)
union node *argp;
struct strlist *sp;
struct stackmark smark;
+ int status;
setstackmark(&smark);
arglist.lastp = &arglist.list;
@@ -346,11 +358,12 @@ evalfor(union node *n, int flags)
}
*arglist.lastp = NULL;
- exitstatus = 0;
loopnest++;
+ status = 0;
for (sp = arglist.list ; sp ; sp = sp->next) {
setvar(n->nfor.var, sp->text, 0);
evaltree(n->nfor.body, flags);
+ status = exitstatus;
if (evalskip) {
if (evalskip == SKIPCONT && --skipcount <= 0) {
evalskip = 0;
@@ -363,12 +376,18 @@ evalfor(union node *n, int flags)
}
loopnest--;
popstackmark(&smark);
+ exitstatus = status;
}
+/*
+ * Evaluate a case statement, returning the selected tree.
+ *
+ * The exit status needs care to get right.
+ */
static union node *
-evalcase(union node *n, int flags)
+evalcase(union node *n)
{
union node *cp;
union node *patp;
@@ -378,25 +397,26 @@ evalcase(union node *n, int flags)
setstackmark(&smark);
arglist.lastp = &arglist.list;
oexitstatus = exitstatus;
- exitstatus = 0;
expandarg(n->ncase.expr, &arglist, EXP_TILDE);
for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) {
for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
if (casematch(patp, arglist.list->text)) {
popstackmark(&smark);
while (cp->nclist.next &&
- cp->type == NCLISTFALLTHRU) {
- evaltree(cp->nclist.body,
- flags & ~EV_EXIT);
- if (evalskip != 0)
- return (NULL);
+ cp->type == NCLISTFALLTHRU &&
+ cp->nclist.body == NULL)
cp = cp->nclist.next;
- }
+ if (cp->nclist.next &&
+ cp->type == NCLISTFALLTHRU)
+ return (cp);
+ if (cp->nclist.body == NULL)
+ exitstatus = 0;
return (cp->nclist.body);
}
}
}
popstackmark(&smark);
+ exitstatus = 0;
return (NULL);
}
@@ -978,7 +998,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
memout.nextc = memout.buf;
memout.bufsize = 64;
mode |= REDIR_BACKQ;
- cmdentry.special = 0;
}
savecmdname = commandname;
savetopfile = getcurrentfile();
@@ -999,7 +1018,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
* If there is no command word, redirection errors should
* not be fatal but assignment errors should.
*/
- if (argc == 0 && !(flags & EV_BACKCMD))
+ if (argc == 0)
cmdentry.special = 1;
listsetvar(cmdenviron, cmdentry.special ? 0 : VNOSET);
if (argc > 0)
diff --git a/bin/sh/eval.h b/bin/sh/eval.h
index fba6f9a..724e157 100644
--- a/bin/sh/eval.h
+++ b/bin/sh/eval.h
@@ -60,6 +60,7 @@ void evalbackcmd(union node *, struct backcmd *);
#define in_function() funcnest
extern int funcnest;
extern int evalskip;
+extern int skipcount;
/* reasons for skipping commands (see comment on breakcmd routine) */
#define SKIPBREAK 1
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index 044fc30..82cb3ac 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -100,6 +100,7 @@ static void tryexec(char *, char **, char **);
static void printentry(struct tblentry *, int);
static struct tblentry *cmdlookup(const char *, int);
static void delete_cmd_entry(void);
+static void addcmdentry(const char *, struct cmdentry *);
@@ -492,7 +493,7 @@ hashcd(void)
*/
void
-changepath(const char *newval)
+changepath(const char *newval __unused)
{
clearcmdentry();
}
@@ -593,7 +594,7 @@ delete_cmd_entry(void)
* the same name.
*/
-void
+static void
addcmdentry(const char *name, struct cmdentry *entry)
{
struct tblentry *cmdp;
diff --git a/bin/sh/exec.h b/bin/sh/exec.h
index 31f11c0..0948421 100644
--- a/bin/sh/exec.h
+++ b/bin/sh/exec.h
@@ -70,7 +70,6 @@ void find_command(const char *, struct cmdentry *, int, const char *);
int find_builtin(const char *, int *);
void hashcd(void);
void changepath(const char *);
-void addcmdentry(const char *, struct cmdentry *);
void defun(const char *, union node *);
int unsetfunc(const char *);
int typecmd_impl(int, char **, int, const char *);
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index ea8d78d..d43cc35 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -113,6 +113,7 @@ static void expmeta(char *, char *);
static void addfname(char *);
static struct strlist *expsort(struct strlist *);
static struct strlist *msort(struct strlist *, int);
+static int patmatch(const char *, const char *, int);
static char *cvtnum(int, char *);
static int collate_range_cmp(wchar_t, wchar_t);
@@ -1186,6 +1187,7 @@ expmeta(char *enddir, char *name)
int atend;
int matchdot;
int esc;
+ int namlen;
metaflag = 0;
start = name;
@@ -1284,17 +1286,22 @@ expmeta(char *enddir, char *name)
if (dp->d_name[0] == '.' && ! matchdot)
continue;
if (patmatch(start, dp->d_name, 0)) {
- if (enddir + dp->d_namlen + 1 > expdir_end)
+ namlen = dp->d_namlen;
+ if (enddir + namlen + 1 > expdir_end)
continue;
- memcpy(enddir, dp->d_name, dp->d_namlen + 1);
+ memcpy(enddir, dp->d_name, namlen + 1);
if (atend)
addfname(expdir);
else {
- if (enddir + dp->d_namlen + 2 > expdir_end)
+ if (dp->d_type != DT_UNKNOWN &&
+ dp->d_type != DT_DIR &&
+ dp->d_type != DT_LNK)
continue;
- enddir[dp->d_namlen] = '/';
- enddir[dp->d_namlen + 1] = '\0';
- expmeta(enddir + dp->d_namlen + 1, endname);
+ if (enddir + namlen + 2 > expdir_end)
+ continue;
+ enddir[namlen] = '/';
+ enddir[namlen + 1] = '\0';
+ expmeta(enddir + namlen + 1, endname);
}
}
}
@@ -1435,61 +1442,67 @@ match_charclass(const char *p, wchar_t chr, const char **end)
* Returns true if the pattern matches the string.
*/
-int
+static int
patmatch(const char *pattern, const char *string, int squoted)
{
const char *p, *q, *end;
+ const char *bt_p, *bt_q;
char c;
wchar_t wc, wc2;
p = pattern;
q = string;
+ bt_p = NULL;
+ bt_q = NULL;
for (;;) {
switch (c = *p++) {
case '\0':
- goto breakloop;
+ if (*q != '\0')
+ goto backtrack;
+ return 1;
case CTLESC:
if (squoted && *q == CTLESC)
q++;
if (*q++ != *p++)
- return 0;
+ goto backtrack;
break;
case CTLQUOTEMARK:
continue;
case '?':
if (squoted && *q == CTLESC)
q++;
- if (localeisutf8)
+ if (*q == '\0')
+ return 0;
+ if (localeisutf8) {
wc = get_wc(&q);
- else
+ /*
+ * A '?' does not match invalid UTF-8 but a
+ * '*' does, so backtrack.
+ */
+ if (wc == 0)
+ goto backtrack;
+ } else
wc = (unsigned char)*q++;
- if (wc == '\0')
- return 0;
break;
case '*':
c = *p;
while (c == CTLQUOTEMARK || c == '*')
c = *++p;
- if (c != CTLESC && c != CTLQUOTEMARK &&
- c != '?' && c != '*' && c != '[') {
- while (*q != c) {
- if (squoted && *q == CTLESC &&
- q[1] == c)
- break;
- if (*q == '\0')
- return 0;
- if (squoted && *q == CTLESC)
- q++;
- q++;
- }
- }
- do {
- if (patmatch(p, q, squoted))
- return 1;
- if (squoted && *q == CTLESC)
- q++;
- } while (*q++ != '\0');
- return 0;
+ /*
+ * If the pattern ends here, we know the string
+ * matches without needing to look at the rest of it.
+ */
+ if (c == '\0')
+ return 1;
+ /*
+ * First try the shortest match for the '*' that
+ * could work. We can forget any earlier '*' since
+ * there is no way having it match more characters
+ * can help us, given that we are already here.
+ */
+ bt_p = p;
+ bt_q = q;
+ break;
case '[': {
const char *endp;
int invert, found;
@@ -1501,7 +1514,7 @@ patmatch(const char *pattern, const char *string, int squoted)
for (;;) {
while (*endp == CTLQUOTEMARK)
endp++;
- if (*endp == '\0')
+ if (*endp == 0)
goto dft; /* no matching ] */
if (*endp == CTLESC)
endp++;
@@ -1516,12 +1529,14 @@ patmatch(const char *pattern, const char *string, int squoted)
found = 0;
if (squoted && *q == CTLESC)
q++;
- if (localeisutf8)
+ if (*q == '\0')
+ return 0;
+ if (localeisutf8) {
chr = get_wc(&q);
- else
+ if (chr == 0)
+ goto backtrack;
+ } else
chr = (unsigned char)*q++;
- if (chr == '\0')
- return 0;
c = *p++;
do {
if (c == CTLQUOTEMARK)
@@ -1562,21 +1577,34 @@ patmatch(const char *pattern, const char *string, int squoted)
}
} while ((c = *p++) != ']');
if (found == invert)
- return 0;
+ goto backtrack;
break;
}
dft: default:
if (squoted && *q == CTLESC)
q++;
- if (*q++ != c)
+ if (*q == '\0')
+ return 0;
+ if (*q++ == c)
+ break;
+backtrack:
+ /*
+ * If we have a mismatch (other than hitting the end
+ * of the string), go back to the last '*' seen and
+ * have it match one additional character.
+ */
+ if (bt_p == NULL)
+ return 0;
+ if (squoted && *bt_q == CTLESC)
+ bt_q++;
+ if (*bt_q == '\0')
return 0;
+ bt_q++;
+ p = bt_p;
+ q = bt_q;
break;
}
}
-breakloop:
- if (*q != '\0')
- return 0;
- return 1;
}
diff --git a/bin/sh/expand.h b/bin/sh/expand.h
index 5029552..8114e2b 100644
--- a/bin/sh/expand.h
+++ b/bin/sh/expand.h
@@ -60,6 +60,5 @@ union node;
void expandhere(union node *, int);
void expandarg(union node *, struct arglist *, int);
void expari(int);
-int patmatch(const char *, const char *, int);
void rmescapes(char *);
int casematch(union node *, const char *);
diff --git a/bin/sh/funcs/kill b/bin/sh/funcs/kill
deleted file mode 100644
index 16f0c9b..0000000
--- a/bin/sh/funcs/kill
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/sh
-
-#-
-# Copyright (c) 1991, 1993
-# The Regents of the University of California. All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 4. Neither the name of the University nor the names of its contributors
-# may be used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# @(#)kill 8.2 (Berkeley) 5/4/95
-# $FreeBSD$
-
-# Convert job names to process ids and then run /bin/kill.
-
-kill() {
- local args x
- args=
- for x in "$@"
- do case $x in
- %*) x=`jobid "$x"` ;;
- esac
- args="$args $x"
- done
- /bin/kill $args
-}
diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index 4619baf..6371599 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -70,6 +70,8 @@ int displayhist;
static FILE *el_in, *el_out, *el_err;
static char *fc_replace(const char *, char *, char *);
+static int not_fcnumber(const char *);
+static int str_to_event(const char *, int);
/*
* Set history and editing status. Called whenever the status may
@@ -158,8 +160,7 @@ bad:
void
-sethistsize(hs)
- const char *hs;
+sethistsize(const char *hs)
{
int histsize;
HistEvent he;
@@ -425,7 +426,7 @@ fc_replace(const char *s, char *p, char *r)
return (dest);
}
-int
+static int
not_fcnumber(const char *s)
{
if (s == NULL)
@@ -435,7 +436,7 @@ not_fcnumber(const char *s)
return (!is_number(s));
}
-int
+static int
str_to_event(const char *str, int last)
{
HistEvent he;
diff --git a/bin/sh/input.c b/bin/sh/input.c
index c8b1a45..3ceaea4 100644
--- a/bin/sh/input.c
+++ b/bin/sh/input.c
@@ -97,7 +97,7 @@ int parsenleft; /* copy of parsefile->nleft */
MKINIT int parselleft; /* copy of parsefile->lleft */
char *parsenextc; /* copy of parsefile->nextc */
MKINIT struct parsefile basepf; /* top level input file */
-char basebuf[BUFSIZ]; /* buffer for top level input file */
+char basebuf[BUFSIZ + 1]; /* buffer for top level input file */
static struct parsefile *parsefile = &basepf; /* current input file */
int init_editline = 0; /* editline library initialized? */
int whichprompt; /* 1 == PS1, 2 == PS2 */
@@ -106,6 +106,7 @@ EditLine *el; /* cookie for editline package */
static void pushfile(void);
static int preadfd(void);
+static void popstring(void);
#ifdef mkinit
INCLUDE "input.h"
@@ -188,8 +189,8 @@ retry:
nr = 0;
else {
nr = el_len;
- if (nr > BUFSIZ - 1)
- nr = BUFSIZ - 1;
+ if (nr > BUFSIZ)
+ nr = BUFSIZ;
memcpy(parsenextc, rl_cp, nr);
if (nr != el_len) {
el_len -= nr;
@@ -199,7 +200,7 @@ retry:
}
} else
#endif
- nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
+ nr = read(parsefile->fd, parsenextc, BUFSIZ);
if (nr <= 0) {
if (nr < 0) {
@@ -372,7 +373,7 @@ pushstring(char *s, int len, void *ap)
INTON;
}
-void
+static void
popstring(void)
{
struct strpush *sp = parsefile->strpush;
@@ -427,13 +428,13 @@ setinputfd(int fd, int push)
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
if (push) {
pushfile();
- parsefile->buf = ckmalloc(BUFSIZ);
+ parsefile->buf = ckmalloc(BUFSIZ + 1);
}
if (parsefile->fd > 0)
close(parsefile->fd);
parsefile->fd = fd;
if (parsefile->buf == NULL)
- parsefile->buf = ckmalloc(BUFSIZ);
+ parsefile->buf = ckmalloc(BUFSIZ + 1);
parselleft = parsenleft = 0;
plinno = 1;
}
diff --git a/bin/sh/input.h b/bin/sh/input.h
index abbb2ce..92aba45 100644
--- a/bin/sh/input.h
+++ b/bin/sh/input.h
@@ -53,7 +53,6 @@ int preadbuffer(void);
int preadateof(void);
void pungetc(void);
void pushstring(char *, int, void *);
-void popstring(void);
void setinputfile(const char *, int);
void setinputfd(int, int);
void setinputstring(char *, int);
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index 75b503e..232be8b 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -92,6 +92,7 @@ static void restartjob(struct job *);
#endif
static void freejob(struct job *);
static struct job *getjob(char *);
+pid_t getjobpgrp(char *);
static pid_t dowait(int, struct job *);
static pid_t waitproc(int, int *);
static void checkzombies(void);
diff --git a/bin/sh/main.c b/bin/sh/main.c
index e6c8a20..5eb12e0 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -79,6 +79,7 @@ int rootshell;
struct jmploc main_handler;
int localeisutf8, initial_localeisutf8;
+static void cmdloop(int);
static void read_profile(char *);
static char *find_dot_file(char *);
@@ -184,7 +185,7 @@ state4: /* XXX ??? - why isn't this before the "if" statement */
* loop; it turns on prompting if the shell is interactive.
*/
-void
+static void
cmdloop(int top)
{
union node *n;
diff --git a/bin/sh/main.h b/bin/sh/main.h
index 6d4cc4a..3c48e33 100644
--- a/bin/sh/main.h
+++ b/bin/sh/main.h
@@ -38,4 +38,3 @@ extern int rootshell; /* true if we aren't a child of the main shell */
extern struct jmploc main_handler; /* top level exception handler */
void readcmdfile(const char *);
-void cmdloop(int);
diff --git a/bin/sh/mksyntax.c b/bin/sh/mksyntax.c
index 9aa7450..07dc2f1 100644
--- a/bin/sh/mksyntax.c
+++ b/bin/sh/mksyntax.c
@@ -219,16 +219,16 @@ main(int argc __unused, char **argv __unused)
add("`", "CBQUOTE");
add("$", "CVAR");
add("}", "CENDVAR");
- /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
- add("!*?[=~:/-", "CCTL");
+ /* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
+ add("!*?[]=~:/-^", "CCTL");
print("dqsyntax");
init();
fputs("\n/* syntax table used when in single quotes */\n", cfile);
add("\n", "CNL");
add("\\", "CSBACK");
add("'", "CENDQUOTE");
- /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
- add("!*?[=~:/-", "CCTL");
+ /* ':/' for tilde expansion, '-^]' for [a\-x] pattern ranges */
+ add("!*?[]=~:/-^", "CCTL");
print("sqsyntax");
init();
fputs("\n/* syntax table used when in arithmetic */\n", cfile);
diff --git a/bin/sh/myhistedit.h b/bin/sh/myhistedit.h
index 9a649ec..e31276d 100644
--- a/bin/sh/myhistedit.h
+++ b/bin/sh/myhistedit.h
@@ -39,6 +39,4 @@ extern int displayhist;
void histedit(void);
void sethistsize(const char *);
void setterm(const char *);
-int not_fcnumber(const char *);
-int str_to_event(const char *, int);
diff --git a/bin/sh/mystring.c b/bin/sh/mystring.c
index 53d703d..67617ec 100644
--- a/bin/sh/mystring.c
+++ b/bin/sh/mystring.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
*
* equal(s1, s2) Return true if strings are equal.
* scopy(from, to) Copy a string.
- * scopyn(from, to, n) Like scopy, but checks for overflow.
* number(s) Convert a string of digits to an integer.
* is_number(s) Return true if s is a string of digits.
*/
@@ -67,24 +66,6 @@ char nullstr[1]; /* zero length string */
/*
- * scopyn - copy a string from "from" to "to", truncating the string
- * if necessary. "To" is always nul terminated, even if
- * truncation is performed. "Size" is the size of "to".
- */
-
-void
-scopyn(const char *from, char *to, int size)
-{
-
- while (--size > 0) {
- if ((*to++ = *from++) == '\0')
- return;
- }
- *to = '\0';
-}
-
-
-/*
* prefix -- see if pfx is a prefix of string.
*/
diff --git a/bin/sh/mystring.h b/bin/sh/mystring.h
index 1b27a1b..5a6e3d8 100644
--- a/bin/sh/mystring.h
+++ b/bin/sh/mystring.h
@@ -35,7 +35,6 @@
#include <string.h>
-void scopyn(const char *, char *, int);
int prefix(const char *, const char *);
int number(const char *);
int is_number(const char *);
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index 2b6d8a5..834992f 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -191,10 +191,11 @@ trapcmd(int argc, char **argv)
argv++;
}
}
- while (*argv) {
+ for (; *argv; argv++) {
if ((signo = sigstring_to_signum(*argv)) == -1) {
warning("bad signal %s", *argv);
errors = 1;
+ continue;
}
INTOFF;
if (action)
@@ -205,7 +206,6 @@ trapcmd(int argc, char **argv)
if (signo != 0)
setsignal(signo);
INTON;
- argv++;
}
return errors;
}
@@ -412,7 +412,7 @@ void
dotrap(void)
{
int i;
- int savestatus;
+ int savestatus, prev_evalskip, prev_skipcount;
in_dotrap++;
for (;;) {
@@ -427,10 +427,36 @@ dotrap(void)
*/
if (i == SIGCHLD)
ignore_sigchld++;
+
+ /*
+ * Backup current evalskip
+ * state and reset it before
+ * executing a trap, so that the
+ * trap is not disturbed by an
+ * ongoing break/continue/return
+ * statement.
+ */
+ prev_evalskip = evalskip;
+ prev_skipcount = skipcount;
+ evalskip = 0;
+
last_trapsig = i;
savestatus = exitstatus;
evalstring(trap[i], 0);
exitstatus = savestatus;
+
+ /*
+ * If such a command was not
+ * already in progress, allow a
+ * break/continue/return in the
+ * trap action to have an effect
+ * outside of it.
+ */
+ if (prev_evalskip != 0) {
+ evalskip = prev_evalskip;
+ skipcount = prev_skipcount;
+ }
+
if (i == SIGCHLD)
ignore_sigchld--;
}
@@ -501,6 +527,11 @@ exitshell_savedstatus(void)
}
handler = &loc1;
if ((p = trap[0]) != NULL && *p != '\0') {
+ /*
+ * Reset evalskip, or the trap on EXIT could be
+ * interrupted if the last command was a "return".
+ */
+ evalskip = 0;
trap[0] = NULL;
evalstring(p, 0);
}
OpenPOWER on IntegriCloud