summaryrefslogtreecommitdiffstats
path: root/bin/sh
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/arith_yacc.c2
-rw-r--r--bin/sh/eval.c19
-rw-r--r--bin/sh/mkinit.c1
-rw-r--r--bin/sh/mktokens1
-rw-r--r--bin/sh/nodetypes4
-rw-r--r--bin/sh/options.h4
-rw-r--r--bin/sh/parser.c19
-rw-r--r--bin/sh/sh.191
-rw-r--r--bin/sh/var.c13
9 files changed, 122 insertions, 32 deletions
diff --git a/bin/sh/arith_yacc.c b/bin/sh/arith_yacc.c
index f1ac59e..041e638 100644
--- a/bin/sh/arith_yacc.c
+++ b/bin/sh/arith_yacc.c
@@ -35,7 +35,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/limits.h>
+#include <limits.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 9d67b9e..d5da7d3 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -140,7 +140,7 @@ evalcmd(int argc, char **argv)
STPUTC('\0', concat);
p = grabstackstr(concat);
}
- evalstring(p, builtin_flags & EV_TESTED);
+ evalstring(p, builtin_flags);
} else
exitstatus = 0;
return exitstatus;
@@ -386,6 +386,14 @@ evalcase(union node *n, int flags)
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)) {
+ while (cp->nclist.next &&
+ cp->type == NCLISTFALLTHRU) {
+ if (evalskip != 0)
+ break;
+ evaltree(cp->nclist.body,
+ flags & ~EV_EXIT);
+ cp = cp->nclist.next;
+ }
if (evalskip == 0) {
evaltree(cp->nclist.body, flags);
}
@@ -886,14 +894,13 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
}
/* Fork off a child process if necessary. */
- if (cmd->ncmd.backgnd
- || ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
+ if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
&& ((flags & EV_EXIT) == 0 || have_traps()))
|| ((flags & EV_BACKCMD) != 0
&& (cmdentry.cmdtype != CMDBUILTIN ||
!safe_builtin(cmdentry.u.index, argc, argv)))) {
jp = makejob(cmd, 1);
- mode = cmd->ncmd.backgnd;
+ mode = FORK_FG;
if (flags & EV_BACKCMD) {
mode = FORK_NOJOB;
if (pipe(pip) < 0)
@@ -908,6 +915,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
dup2(pip[1], 1);
close(pip[1]);
}
+ flags &= ~EV_BACKCMD;
}
flags |= EV_EXIT;
}
@@ -1059,8 +1067,7 @@ parent: /* parent process gets here (if we forked) */
backcmd->fd = pip[0];
close(pip[1]);
backcmd->jp = jp;
- } else
- exitstatus = 0;
+ }
out:
if (lastarg)
diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c
index 866b238..1d1d93e 100644
--- a/bin/sh/mkinit.c
+++ b/bin/sh/mkinit.c
@@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
*/
-#include <sys/cdefs.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/bin/sh/mktokens b/bin/sh/mktokens
index b85c8cb9..82d7cd7 100644
--- a/bin/sh/mktokens
+++ b/bin/sh/mktokens
@@ -50,6 +50,7 @@ TPIPE 0 "|"
TLP 0 "("
TRP 1 ")"
TENDCASE 1 ";;"
+TFALLTHRU 1 ";&"
TREDIR 0 redirection
TWORD 0 word
TIF 0 "if"
diff --git a/bin/sh/nodetypes b/bin/sh/nodetypes
index e1e1b04..ae4bc4a 100644
--- a/bin/sh/nodetypes
+++ b/bin/sh/nodetypes
@@ -56,7 +56,6 @@ NSEMI nbinary # two commands separated by a semicolon
NCMD ncmd # a simple command
type int
- backgnd int # set to run command in background
args nodeptr # the arguments
redirect nodeptr # list of file redirections
@@ -96,12 +95,13 @@ NCASE ncase # a case statement
expr nodeptr # the word to switch on
cases nodeptr # the list of cases (NCLIST nodes)
-NCLIST nclist # a case
+NCLIST nclist # a case ending with ;;
type int
next nodeptr # the next case in list
pattern nodeptr # list of patterns for this case
body nodeptr # code to execute for this case
+NCLISTFALLTHRU nclist # a case ending with ;&
NDEFUN narg # define a function. The "next" field contains
# the body of the function.
diff --git a/bin/sh/options.h b/bin/sh/options.h
index f3d3d3d..acc2a11 100644
--- a/bin/sh/options.h
+++ b/bin/sh/options.h
@@ -62,8 +62,9 @@ struct shparam {
#define privileged optlist[15].val
#define Tflag optlist[16].val
#define Pflag optlist[17].val
+#define hflag optlist[18].val
-#define NOPTS 18
+#define NOPTS 19
struct optent {
const char *name;
@@ -91,6 +92,7 @@ struct optent optlist[NOPTS] = {
{ "privileged", 'p', 0 },
{ "trapsasync", 'T', 0 },
{ "physical", 'P', 0 },
+ { "trackall", 'h', 0 },
};
#else
extern struct optent optlist[NOPTS];
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index 2fea1ec..ef1aa36 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -240,8 +240,8 @@ list(int nlflag, int erflag)
n2 = andor();
tok = readtoken();
if (tok == TBACKGND) {
- if (n2->type == NCMD || n2->type == NPIPE) {
- n2->ncmd.backgnd = 1;
+ if (n2->type == NPIPE) {
+ n2->npipe.backgnd = 1;
} else if (n2->type == NREDIR) {
n2->type = NBACKGND;
} else {
@@ -542,10 +542,13 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
checkkwd = CHKNL | CHKKWD | CHKALIAS;
if ((t = readtoken()) != TESAC) {
- if (t != TENDCASE)
- synexpect(TENDCASE);
+ if (t == TENDCASE)
+ ;
+ else if (t == TFALLTHRU)
+ cp->type = NCLISTFALLTHRU;
else
- checkkwd = CHKNL | CHKKWD, readtoken();
+ synexpect(TENDCASE);
+ checkkwd = CHKNL | CHKKWD, readtoken();
}
cpp = &cp->nclist.next;
}
@@ -686,7 +689,6 @@ simplecmd(union node **rpp, union node *redir)
*rpp = NULL;
n = (union node *)stalloc(sizeof (struct ncmd));
n->type = NCMD;
- n->ncmd.backgnd = 0;
n->ncmd.args = args;
n->ncmd.redirect = redir;
return n;
@@ -931,8 +933,11 @@ xxreadtoken(void)
pungetc();
RETURN(TPIPE);
case ';':
- if (pgetc() == ';')
+ c = pgetc();
+ if (c == ';')
RETURN(TENDCASE);
+ else if (c == '&')
+ RETURN(TFALLTHRU);
pungetc();
RETURN(TSEMI);
case '(':
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 67ffcc6..bbb0f49 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd June 15, 2011
+.Dd July 10, 2011
.Dt SH 1
.Os
.Sh NAME
@@ -241,6 +241,10 @@ tested, all commands of the function are considered to be tested as
well.
.It Fl f Li noglob
Disable pathname expansion.
+.It Fl h Li trackall
+A do-nothing option for
+.Tn POSIX
+compliance.
.It Fl I Li ignoreeof
Ignore
.Dv EOF Ap s
@@ -372,7 +376,7 @@ The following is a list of valid operators:
.It Control operators:
.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact
.It Li & Ta Li && Ta Li ( Ta Li ) Ta Li \en
-.It Li ;; Ta Li ; Ta Li | Ta Li ||
+.It Li ;; Ta Li ;& Ta Li ; Ta Li | Ta Li ||
.El
.It Redirection operators:
.Bl -column "XXX" "XXX" "XXX" "XXX" "XXX" -offset center -compact
@@ -857,7 +861,9 @@ causes asynchronous execution of the preceding AND-OR-list.
.Ss Background Commands (&)
If a command is terminated by the control operator ampersand
.Pq Ql & ,
-the shell executes the command asynchronously;
+the shell executes the command in a subshell environment (see
+.Sx Grouping Commands Together
+below) and asynchronously;
the shell does not wait for the command to finish
before executing the next command.
.Pp
@@ -990,6 +996,22 @@ described later),
separated by
.Ql \&|
characters.
+Tilde expansion, parameter expansion, command substitution,
+arithmetic expansion and quote removal are applied to the word.
+Then, each pattern is expanded in turn using tilde expansion,
+parameter expansion, command substitution and arithmetic expansion and
+the expanded form of the word is checked against it.
+If a match is found, the corresponding list is executed.
+If the selected list is terminated by the control operator
+.Ql ;&
+instead of
+.Ql ;; ,
+execution continues with the next list,
+continuing until a list terminated with
+.Ql ;;
+or the end of the
+.Ic case
+command.
The exit code of the
.Ic case
command is the exit code of the last command executed in the list or
@@ -1004,7 +1026,41 @@ or
.D1 Li { Ar list Ns Li \&; }
.Pp
The first form executes the commands in a subshell environment.
-Note that built-in commands thus executed do not affect the current shell.
+A subshell environment has its own copy of:
+.Pp
+.Bl -enum
+.It
+The current working directory as set by
+.Ic cd .
+.It
+The file creation mask as set by
+.Ic umask .
+.It
+References to open files.
+.It
+Traps as set by
+.Ic trap .
+.It
+Known jobs.
+.It
+Positional parameters and variables.
+.It
+Shell options.
+.It
+Shell functions.
+.It
+Shell aliases.
+.El
+.Pp
+These are copied from the parent shell environment,
+except that trapped (but not ignored) signals are reset to the default action
+and known jobs are cleared.
+Any changes do not affect the parent shell environment.
+.Pp
+A subshell environment may be implemented as a child process or differently.
+If job control is enabled in an interactive shell,
+commands grouped in parentheses can be suspended and continued as a unit.
+.Pp
The second form never forks another shell,
so it is slightly more efficient.
Grouping commands together this way allows the user to
@@ -1532,10 +1588,12 @@ The command is executed in a subshell environment,
except that the built-in commands
.Ic jobid ,
.Ic jobs ,
-.Ic times
and
.Ic trap
-return information about the main shell environment
+return information about the parent shell environment
+and
+.Ic times
+returns information about the same process
if they are the only command in a command substitution.
.Ss Arithmetic Expansion
Arithmetic expansion provides a mechanism for evaluating an arithmetic
@@ -1609,15 +1667,15 @@ There are two restrictions on this: first, a pattern cannot match
a string containing a slash, and second,
a pattern cannot match a string starting with a period
unless the first character of the pattern is a period.
-The next section describes the patterns used for both
-Pathname Expansion and the
+The next section describes the patterns used for
+Pathname Expansion,
+the four varieties of parameter expansion for substring processing and the
.Ic case
command.
.Ss Shell Patterns
A pattern consists of normal characters, which match themselves,
and meta-characters.
The meta-characters are
-.Ql \&! ,
.Ql * ,
.Ql \&? ,
and
@@ -1647,7 +1705,7 @@ matches a
.Ql \&[
rather than introducing a character class.
A character class matches any of the characters between the square brackets.
-A range of characters may be specified using a minus sign.
+A locale-dependent range of characters may be specified using a minus sign.
A named class of characters (see
.Xr wctype 3 )
may be specified by surrounding the name with
@@ -1660,12 +1718,17 @@ is a shell pattern that matches a single letter.
The character class may be complemented by making an exclamation point
.Pq Ql !\&
the first character of the character class.
+A caret
+.Pq Ql ^
+has the same effect but is non-standard.
.Pp
To include a
.Ql \&]
in a character class, make it the first character listed
(after the
-.Ql \&! ,
+.Ql \&!
+or
+.Ql ^ ,
if any).
To include a
.Ql - ,
@@ -2334,8 +2397,8 @@ If there are zero positional parameters, shifting does not do anything.
A built-in equivalent of
.Xr test 1 .
.It Ic times
-Print the amount of time spent executing the shell and its children.
-The first output line shows the user and system times for the shell
+Print the amount of time spent executing the shell process and its children.
+The first output line shows the user and system times for the shell process
itself, the second one contains the user and system times for the
children.
.It Ic trap Oo Ar action Oc Ar signal ...
@@ -2361,7 +2424,7 @@ Omitting the
.Ar action
is another way to request the default action, for compatibility reasons this
usage is not recommended though.
-In a subshell environment,
+In a subshell or utility environment,
the shell resets trapped (but not ignored) signals to the default action.
The
.Ic trap
diff --git a/bin/sh/var.c b/bin/sh/var.c
index d5b2522..b3bc6f7f 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -612,6 +612,12 @@ showvarscmd(int argc __unused, char **argv __unused)
qsort(vars, n, sizeof(*vars), var_compare);
for (i = 0; i < n; i++) {
+ /*
+ * Skip improper variable names so the output remains usable as
+ * shell input.
+ */
+ if (!isassignment(vars[i]))
+ continue;
s = strchr(vars[i], '=');
s++;
outbin(vars[i], s - vars[i], out1);
@@ -683,6 +689,13 @@ exportcmd(int argc, char **argv)
for (vp = *vpp ; vp ; vp = vp->next) {
if (vp->flags & flag) {
if (values) {
+ /*
+ * Skip improper variable names
+ * so the output remains usable
+ * as shell input.
+ */
+ if (!isassignment(vp->text))
+ continue;
out1str(cmdname);
out1c(' ');
}
OpenPOWER on IntegriCloud