diff options
author | jimharris <jimharris@FreeBSD.org> | 2012-01-26 15:23:45 +0000 |
---|---|---|
committer | jimharris <jimharris@FreeBSD.org> | 2012-01-26 15:23:45 +0000 |
commit | bcd0e15cf642d6e5bf78ee585ad282b0e3061864 (patch) | |
tree | 4b7b6096856cdeb36fcba0adf3f4d121a52cce21 /bin/sh | |
parent | 0cf3f853641c2ededc243c9f2139ac6a0b681fe4 (diff) | |
parent | a479ceccdf3646c7bc3ff60796c765650b3ffc03 (diff) | |
download | FreeBSD-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.c | 3 | ||||
-rw-r--r-- | bin/sh/arith_yylex.c | 2 | ||||
-rw-r--r-- | bin/sh/cd.c | 7 | ||||
-rw-r--r-- | bin/sh/eval.c | 47 | ||||
-rw-r--r-- | bin/sh/eval.h | 1 | ||||
-rw-r--r-- | bin/sh/exec.c | 5 | ||||
-rw-r--r-- | bin/sh/exec.h | 1 | ||||
-rw-r--r-- | bin/sh/expand.c | 116 | ||||
-rw-r--r-- | bin/sh/expand.h | 1 | ||||
-rw-r--r-- | bin/sh/funcs/kill | 49 | ||||
-rw-r--r-- | bin/sh/histedit.c | 9 | ||||
-rw-r--r-- | bin/sh/input.c | 15 | ||||
-rw-r--r-- | bin/sh/input.h | 1 | ||||
-rw-r--r-- | bin/sh/jobs.c | 1 | ||||
-rw-r--r-- | bin/sh/main.c | 3 | ||||
-rw-r--r-- | bin/sh/main.h | 1 | ||||
-rw-r--r-- | bin/sh/mksyntax.c | 8 | ||||
-rw-r--r-- | bin/sh/myhistedit.h | 2 | ||||
-rw-r--r-- | bin/sh/mystring.c | 19 | ||||
-rw-r--r-- | bin/sh/mystring.h | 1 | ||||
-rw-r--r-- | bin/sh/trap.c | 37 |
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); } |