summaryrefslogtreecommitdiffstats
path: root/bin/sh
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2013-04-12 20:48:55 +0000
committersjg <sjg@FreeBSD.org>2013-04-12 20:48:55 +0000
commit97d8b9495668afa398ab17c8c5f7e223b5fd2e89 (patch)
tree54038c9ac32a45f8741dcc23fb9a8ffc0e15ff89 /bin/sh
parent5ee3bfdb338e7c80af29a67f4425c4be24c7b866 (diff)
parent086d73aef6d0ab7d21daa2076fdc8d25961f9b05 (diff)
downloadFreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.zip
FreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.tar.gz
sync from head
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/eval.c6
-rw-r--r--bin/sh/exec.c4
-rw-r--r--bin/sh/expand.c13
-rw-r--r--bin/sh/input.c14
-rw-r--r--bin/sh/input.h4
-rw-r--r--bin/sh/jobs.c14
-rw-r--r--bin/sh/main.c6
-rw-r--r--bin/sh/memalloc.c5
-rw-r--r--bin/sh/memalloc.h4
-rw-r--r--bin/sh/nodes.c.pat6
-rw-r--r--bin/sh/parser.c11
-rw-r--r--bin/sh/parser.h2
-rw-r--r--bin/sh/redir.c18
-rw-r--r--bin/sh/sh.115
-rw-r--r--bin/sh/trap.c42
-rw-r--r--bin/sh/trap.h2
16 files changed, 100 insertions, 66 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 66ae40e..d3708b3 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -174,6 +174,7 @@ evalstring(char *s, int flags)
any = 1;
}
popstackmark(&smark);
+ setstackmark(&smark);
}
popfile();
popstackmark(&smark);
@@ -278,6 +279,8 @@ evaltree(union node *n, int flags)
break;
case NNOT:
evaltree(n->nnot.com, EV_TESTED);
+ if (evalskip)
+ goto out;
exitstatus = !exitstatus;
break;
@@ -296,10 +299,11 @@ evaltree(union node *n, int flags)
}
n = next;
popstackmark(&smark);
+ setstackmark(&smark);
} while (n != NULL);
out:
popstackmark(&smark);
- if (pendingsigs)
+ if (pendingsig)
dotrap();
if (eflag && exitstatus != 0 && do_etest)
exitshell(exitstatus);
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index 7a6dbae..6c3a6dd 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -165,7 +165,7 @@ tryexec(char *cmd, char **argv, char **envp)
}
}
*argv = cmd;
- *--argv = _PATH_BSHELL;
+ *--argv = __DECONST(char *, _PATH_BSHELL);
execve(_PATH_BSHELL, argv, envp);
}
errno = e;
@@ -188,7 +188,7 @@ padvance(const char **path, const char *name)
{
const char *p, *start;
char *q;
- int len;
+ size_t len;
if (*path == NULL)
return NULL;
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index 107f798..414bfa7 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -460,7 +460,7 @@ expbackq(union node *cmd, int quoted, int flag)
int startloc = dest - stackblock();
char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
- int nnl;
+ size_t nnl;
INTOFF;
saveifs = ifsfirst;
@@ -1163,9 +1163,9 @@ nometa:
static void
expmeta(char *enddir, char *name)
{
- char *p;
- char *q;
- char *start;
+ const char *p;
+ const char *q;
+ const char *start;
char *endname;
int metaflag;
struct stat statb;
@@ -1229,7 +1229,7 @@ expmeta(char *enddir, char *name)
addfname(expdir);
return;
}
- endname = p;
+ endname = name + (p - name);
if (start != name) {
p = name;
while (p < start) {
@@ -1412,7 +1412,8 @@ match_charclass(const char *p, wchar_t chr, const char **end)
*end = NULL;
p++;
nameend = strstr(p, ":]");
- if (nameend == NULL || nameend - p >= sizeof(name) || nameend == p)
+ if (nameend == NULL || (size_t)(nameend - p) >= sizeof(name) ||
+ nameend == p)
return 0;
memcpy(name, p, nameend - p);
name[nameend - p] = '\0';
diff --git a/bin/sh/input.c b/bin/sh/input.c
index 84580ad..62e82a0 100644
--- a/bin/sh/input.c
+++ b/bin/sh/input.c
@@ -66,7 +66,7 @@ __FBSDID("$FreeBSD$");
struct strpush {
struct strpush *prev; /* preceding string on stack */
- char *prevstring;
+ const char *prevstring;
int prevnleft;
int prevlleft;
struct alias *ap; /* if push was associated with an alias */
@@ -83,7 +83,7 @@ struct parsefile {
int fd; /* file descriptor (or -1 if string) */
int nleft; /* number of chars left in this line */
int lleft; /* number of lines left in this buffer */
- char *nextc; /* next char in buffer */
+ const char *nextc; /* next char in buffer */
char *buf; /* input buffer */
struct strpush *strpush; /* for pushing strings at this level */
struct strpush basestrpush; /* so pushing one is fast */
@@ -93,7 +93,7 @@ struct parsefile {
int plinno = 1; /* input line number */
int parsenleft; /* copy of parsefile->nleft */
MKINIT int parselleft; /* copy of parsefile->lleft */
-char *parsenextc; /* copy of parsefile->nextc */
+const char *parsenextc; /* copy of parsefile->nextc */
static char basebuf[BUFSIZ + 1];/* buffer for top level input file */
static struct parsefile basepf = { /* top level input file */
.nextc = basebuf,
@@ -185,7 +185,7 @@ retry:
nr = el_len;
if (nr > BUFSIZ)
nr = BUFSIZ;
- memcpy(parsenextc, rl_cp, nr);
+ memcpy(parsefile->buf, rl_cp, nr);
if (nr != el_len) {
el_len -= nr;
rl_cp += nr;
@@ -194,7 +194,7 @@ retry:
}
} else
#endif
- nr = read(parsefile->fd, parsenextc, BUFSIZ);
+ nr = read(parsefile->fd, parsefile->buf, BUFSIZ);
if (nr <= 0) {
if (nr < 0) {
@@ -252,7 +252,7 @@ again:
}
}
- q = p = parsenextc;
+ q = p = parsefile->buf + (parsenextc - parsefile->buf);
/* delete nul characters */
something = 0;
@@ -439,7 +439,7 @@ setinputfd(int fd, int push)
*/
void
-setinputstring(char *string, int push)
+setinputstring(const char *string, int push)
{
INTOFF;
if (push)
diff --git a/bin/sh/input.h b/bin/sh/input.h
index c8802f9..70f675e 100644
--- a/bin/sh/input.h
+++ b/bin/sh/input.h
@@ -42,7 +42,7 @@
*/
extern int plinno;
extern int parsenleft; /* number of characters left in input buffer */
-extern char *parsenextc; /* next character in input buffer */
+extern const char *parsenextc; /* next character in input buffer */
struct alias;
struct parsefile;
@@ -55,7 +55,7 @@ void pungetc(void);
void pushstring(char *, int, struct alias *);
void setinputfile(const char *, int);
void setinputfd(int, int);
-void setinputstring(char *, int);
+void setinputstring(const char *, int);
void popfile(void);
struct parsefile *getcurrentfile(void);
void popfilesupto(struct parsefile *);
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index c86394f..c978e3d 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -458,14 +458,15 @@ freejob(struct job *jp)
int
-waitcmd(int argc, char **argv)
+waitcmd(int argc __unused, char **argv __unused)
{
struct job *job;
int status, retval;
struct job *jp;
- if (argc > 1) {
- job = getjob(argv[1]);
+ nextopt("");
+ if (*argptr != NULL) {
+ job = getjob(*argptr);
} else {
job = NULL;
}
@@ -521,7 +522,7 @@ waitcmd(int argc, char **argv)
} while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1);
in_waitcmd--;
- return 0;
+ return pendingsig + 128;
}
@@ -667,7 +668,8 @@ makejob(union node *node __unused, int nprocs)
jobtab = jp;
}
jp = jobtab + njobs;
- for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
+ for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0)
+ ;
INTON;
break;
}
@@ -1004,7 +1006,7 @@ waitforjob(struct job *jp, int *origstatus)
static void
-dummy_handler(int sig)
+dummy_handler(int sig __unused)
{
}
diff --git a/bin/sh/main.c b/bin/sh/main.c
index 66e1335..84a1ef2 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -80,7 +80,7 @@ struct jmploc main_handler;
int localeisutf8, initial_localeisutf8;
static void cmdloop(int);
-static void read_profile(char *);
+static void read_profile(const char *);
static char *find_dot_file(char *);
/*
@@ -196,7 +196,7 @@ cmdloop(int top)
TRACE(("cmdloop(%d) called\n", top));
setstackmark(&smark);
for (;;) {
- if (pendingsigs)
+ if (pendingsig)
dotrap();
inter = 0;
if (iflag && top) {
@@ -239,7 +239,7 @@ cmdloop(int top)
*/
static void
-read_profile(char *name)
+read_profile(const char *name)
{
int fd;
const char *expandedname;
diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c
index bc567d0..f33a15c 100644
--- a/bin/sh/memalloc.c
+++ b/bin/sh/memalloc.c
@@ -233,7 +233,8 @@ growstackblock(int min)
if (min < stacknleft)
min = stacknleft;
- if (min >= INT_MAX / 2 - ALIGN(sizeof(struct stack_block)))
+ if ((unsigned int)min >=
+ INT_MAX / 2 - ALIGN(sizeof(struct stack_block)))
error("Out of space");
min += stacknleft;
min += ALIGN(sizeof(struct stack_block));
@@ -327,7 +328,7 @@ makestrspace(int min, char *p)
char *
-stputbin(const char *data, int len, char *p)
+stputbin(const char *data, size_t len, char *p)
{
CHECKSTRSPACE(len, p);
memcpy(p, data, len);
diff --git a/bin/sh/memalloc.h b/bin/sh/memalloc.h
index 425004e..95a6594 100644
--- a/bin/sh/memalloc.h
+++ b/bin/sh/memalloc.h
@@ -57,7 +57,7 @@ void setstackmark(struct stackmark *);
void popstackmark(struct stackmark *);
char *growstackstr(void);
char *makestrspace(int, char *);
-char *stputbin(const char *data, int len, char *p);
+char *stputbin(const char *data, size_t len, char *p);
char *stputs(const char *data, char *p);
@@ -67,7 +67,7 @@ char *stputs(const char *data, char *p);
#define grabstackblock(n) stalloc(n)
#define STARTSTACKSTR(p) p = stackblock()
#define STPUTC(c, p) do { if (p == sstrend) p = growstackstr(); *p++ = (c); } while(0)
-#define CHECKSTRSPACE(n, p) { if (sstrend - p < n) p = makestrspace(n, p); }
+#define CHECKSTRSPACE(n, p) { if ((size_t)(sstrend - p) < n) p = makestrspace(n, p); }
#define USTPUTC(c, p) (*p++ = (c))
/*
* STACKSTRNUL's use is where we want to be able to turn a stack
diff --git a/bin/sh/nodes.c.pat b/bin/sh/nodes.c.pat
index b325d76..e99e3ab 100644
--- a/bin/sh/nodes.c.pat
+++ b/bin/sh/nodes.c.pat
@@ -58,7 +58,7 @@ static void calcsize(union node *);
static void sizenodelist(struct nodelist *);
static union node *copynode(union node *);
static struct nodelist *copynodelist(struct nodelist *);
-static char *nodesavestr(char *);
+static char *nodesavestr(const char *);
struct funcdef {
@@ -147,9 +147,9 @@ copynodelist(struct nodelist *lp)
static char *
-nodesavestr(char *s)
+nodesavestr(const char *s)
{
- char *p = s;
+ const char *p = s;
char *q = funcstring;
char *rtn = funcstring;
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index 665b53f..073c2b6 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -119,7 +119,7 @@ static void parseheredoc(void);
static int peektoken(void);
static int readtoken(void);
static int xxreadtoken(void);
-static int readtoken1(int, char const *, char *, int);
+static int readtoken1(int, const char *, const char *, int);
static int noexpand(char *);
static void synexpect(int) __dead2;
static void synerror(const char *) __dead2;
@@ -983,7 +983,7 @@ parsebackq(char *out, struct nodelist **pbqlist,
char *volatile str;
struct jmploc jmploc;
struct jmploc *const savehandler = handler;
- int savelen;
+ size_t savelen;
int saveprompt;
const int bq_startlinno = plinno;
char *volatile ostr = NULL;
@@ -1300,7 +1300,8 @@ readcstyleesc(char *out)
#define PARSEARITH() {goto parsearith; parsearith_return:;}
static int
-readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
+readtoken1(int firstc, char const *initialsyntax, const char *eofmark,
+ int striptabs)
{
int c = firstc;
char *out;
@@ -1521,7 +1522,7 @@ checkend: {
}
if (c == *eofmark) {
if (pfgets(line, sizeof line) != NULL) {
- char *p, *q;
+ const char *p, *q;
p = line;
for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
@@ -2038,7 +2039,7 @@ getprompt(void *unused __unused)
const char *
-expandstr(char *ps)
+expandstr(const char *ps)
{
union node n;
struct jmploc jmploc;
diff --git a/bin/sh/parser.h b/bin/sh/parser.h
index f80d917..b803f76 100644
--- a/bin/sh/parser.h
+++ b/bin/sh/parser.h
@@ -82,4 +82,4 @@ void fixredir(union node *, const char *, int);
int goodname(const char *);
int isassignment(const char *);
char *getprompt(void *);
-const char *expandstr(char *);
+const char *expandstr(const char *);
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index c11cb71..fda094d2 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
#define EMPTY -2 /* marks an unused slot in redirtab */
#define CLOSED -1 /* fd was not open before redir */
-#define PIPESIZE 4096 /* amount of buffering in a pipe */
MKINIT
@@ -253,7 +252,9 @@ openhere(union node *redir)
{
char *p;
int pip[2];
- int len = 0;
+ size_t len = 0;
+ int flags;
+ ssize_t written = 0;
if (pipe(pip) < 0)
error("Pipe call failed: %s", strerror(errno));
@@ -263,9 +264,16 @@ openhere(union node *redir)
else
p = redir->nhere.doc->narg.text;
len = strlen(p);
- if (len <= PIPESIZE) {
- xwrite(pip[1], p, len);
+ if (len == 0)
goto out;
+ flags = fcntl(pip[1], F_GETFL, 0);
+ if (flags != -1 && fcntl(pip[1], F_SETFL, flags | O_NONBLOCK) != -1) {
+ written = write(pip[1], p, len);
+ if (written < 0)
+ written = 0;
+ if ((size_t)written == len)
+ goto out;
+ fcntl(pip[1], F_SETFL, flags);
}
if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
@@ -275,7 +283,7 @@ openhere(union node *redir)
signal(SIGHUP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
signal(SIGPIPE, SIG_DFL);
- xwrite(pip[1], p, len);
+ xwrite(pip[1], p + written, len - written);
_exit(0);
}
out:
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 09d94f3..01cb775 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 January 22, 2013
+.Dd March 24, 2013
.Dt SH 1
.Os
.Sh NAME
@@ -1061,6 +1061,9 @@ 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
+For compatibility with other shells,
+two open parentheses in sequence should be separated by whitespace.
+.Pp
The second form never forks another shell,
so it is slightly more efficient.
Grouping commands together this way allows the user to
@@ -1618,6 +1621,16 @@ and
.Ic times
returns information about the same process
if they are the only command in a command substitution.
+.Pp
+If a command substitution of the
+.Li $(
+form begins with a subshell,
+the
+.Li $(
+and
+.Li (\&
+must be separated by whitespace
+to avoid ambiguity with arithmetic expansion.
.Ss Arithmetic Expansion
Arithmetic expansion provides a mechanism for evaluating an arithmetic
expression and substituting its value.
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index 521c511..3138029 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$");
MKINIT char sigmode[NSIG]; /* current value of signal */
-int pendingsigs; /* indicates some signal received */
+volatile sig_atomic_t pendingsig; /* indicates some signal received */
int in_dotrap; /* do we execute in a trap handler? */
static char *volatile trap[NSIG]; /* trap handler commands */
static volatile sig_atomic_t gotsig[NSIG];
@@ -150,7 +150,7 @@ printsignals(void)
* The trap builtin.
*/
int
-trapcmd(int argc, char **argv)
+trapcmd(int argc __unused, char **argv)
{
char *action;
int signo;
@@ -388,22 +388,25 @@ onsig(int signo)
return;
}
- if (signo != SIGCHLD || !ignore_sigchld)
- gotsig[signo] = 1;
- pendingsigs++;
-
/* If we are currently in a wait builtin, prepare to break it */
- if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0)
- breakwaitcmd = 1;
- /*
- * If a trap is set, not ignored and not the null command, we need
- * to make sure traps are executed even when a child blocks signals.
- */
- if (Tflag &&
- trap[signo] != NULL &&
- ! (trap[signo][0] == '\0') &&
- ! (trap[signo][0] == ':' && trap[signo][1] == '\0'))
+ if ((signo == SIGINT || signo == SIGQUIT) && in_waitcmd != 0) {
breakwaitcmd = 1;
+ pendingsig = signo;
+ }
+
+ if (trap[signo] != NULL && trap[signo][0] != '\0' &&
+ (signo != SIGCHLD || !ignore_sigchld)) {
+ gotsig[signo] = 1;
+ pendingsig = signo;
+
+ /*
+ * If a trap is set, not ignored and not the null command, we
+ * need to make sure traps are executed even when a child
+ * blocks signals.
+ */
+ if (Tflag && !(trap[signo][0] == ':' && trap[signo][1] == '\0'))
+ breakwaitcmd = 1;
+ }
#ifndef NO_HISTORY
if (signo == SIGWINCH)
@@ -424,7 +427,7 @@ dotrap(void)
in_dotrap++;
for (;;) {
- pendingsigs = 0;
+ pendingsig = 0;
for (i = 1; i < NSIG; i++) {
if (gotsig[i]) {
gotsig[i] = 0;
@@ -452,7 +455,6 @@ dotrap(void)
last_trapsig = i;
savestatus = exitstatus;
evalstring(trap[i], 0);
- exitstatus = savestatus;
/*
* If such a command was not
@@ -461,9 +463,11 @@ dotrap(void)
* trap action to have an effect
* outside of it.
*/
- if (prev_evalskip != 0) {
+ if (evalskip == 0 ||
+ prev_evalskip != 0) {
evalskip = prev_evalskip;
skipcount = prev_skipcount;
+ exitstatus = savestatus;
}
if (i == SIGCHLD)
diff --git a/bin/sh/trap.h b/bin/sh/trap.h
index 61a17ec..0a05d8d 100644
--- a/bin/sh/trap.h
+++ b/bin/sh/trap.h
@@ -33,7 +33,7 @@
* $FreeBSD$
*/
-extern int pendingsigs;
+extern volatile sig_atomic_t pendingsig;
extern int in_dotrap;
extern volatile sig_atomic_t gotwinch;
OpenPOWER on IntegriCloud