diff options
author | sjg <sjg@FreeBSD.org> | 2013-04-12 20:48:55 +0000 |
---|---|---|
committer | sjg <sjg@FreeBSD.org> | 2013-04-12 20:48:55 +0000 |
commit | 97d8b9495668afa398ab17c8c5f7e223b5fd2e89 (patch) | |
tree | 54038c9ac32a45f8741dcc23fb9a8ffc0e15ff89 /bin/sh | |
parent | 5ee3bfdb338e7c80af29a67f4425c4be24c7b866 (diff) | |
parent | 086d73aef6d0ab7d21daa2076fdc8d25961f9b05 (diff) | |
download | FreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.zip FreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.tar.gz |
sync from head
Diffstat (limited to 'bin/sh')
-rw-r--r-- | bin/sh/eval.c | 6 | ||||
-rw-r--r-- | bin/sh/exec.c | 4 | ||||
-rw-r--r-- | bin/sh/expand.c | 13 | ||||
-rw-r--r-- | bin/sh/input.c | 14 | ||||
-rw-r--r-- | bin/sh/input.h | 4 | ||||
-rw-r--r-- | bin/sh/jobs.c | 14 | ||||
-rw-r--r-- | bin/sh/main.c | 6 | ||||
-rw-r--r-- | bin/sh/memalloc.c | 5 | ||||
-rw-r--r-- | bin/sh/memalloc.h | 4 | ||||
-rw-r--r-- | bin/sh/nodes.c.pat | 6 | ||||
-rw-r--r-- | bin/sh/parser.c | 11 | ||||
-rw-r--r-- | bin/sh/parser.h | 2 | ||||
-rw-r--r-- | bin/sh/redir.c | 18 | ||||
-rw-r--r-- | bin/sh/sh.1 | 15 | ||||
-rw-r--r-- | bin/sh/trap.c | 42 | ||||
-rw-r--r-- | bin/sh/trap.h | 2 |
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; |