diff options
author | Ron Yorston <rmy@pobox.com> | 2018-04-02 09:24:14 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-04-02 09:24:14 +0100 |
commit | 34a68d327b42c3c700e84cd475496985782290b1 (patch) | |
tree | 99bfe59cca420d26f01e81a7f41763f71b44d22c /shell/ash.c | |
parent | aff3c5bd7b6bdcfb97f63153ab839c5f55f16a12 (diff) | |
parent | e84212f8346741a2d4a04b40639c44fe519cf5a7 (diff) | |
download | busybox-w32-34a68d327b42c3c700e84cd475496985782290b1.tar.gz busybox-w32-34a68d327b42c3c700e84cd475496985782290b1.tar.bz2 busybox-w32-34a68d327b42c3c700e84cd475496985782290b1.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 102 |
1 files changed, 49 insertions, 53 deletions
diff --git a/shell/ash.c b/shell/ash.c index 2ab46576c..7448b668a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -282,6 +282,12 @@ typedef long arith_t; | |||
282 | # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ | 282 | # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ |
283 | #endif | 283 | #endif |
284 | 284 | ||
285 | #ifndef F_DUPFD_CLOEXEC | ||
286 | # define F_DUPFD_CLOEXEC F_DUPFD | ||
287 | #endif | ||
288 | #ifndef O_CLOEXEC | ||
289 | # define O_CLOEXEC 0 | ||
290 | #endif | ||
285 | #ifndef PIPE_BUF | 291 | #ifndef PIPE_BUF |
286 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ | 292 | # define PIPE_BUF 4096 /* amount of buffering in a pipe */ |
287 | #endif | 293 | #endif |
@@ -4196,12 +4202,13 @@ setjobctl(int on) | |||
4196 | goto out; | 4202 | goto out; |
4197 | } | 4203 | } |
4198 | /* fd is a tty at this point */ | 4204 | /* fd is a tty at this point */ |
4199 | fd = fcntl(fd, F_DUPFD, 10); | 4205 | fd = fcntl(fd, F_DUPFD_CLOEXEC, 10); |
4200 | if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */ | 4206 | if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */ |
4201 | close(ofd); | 4207 | close(ofd); |
4202 | if (fd < 0) | 4208 | if (fd < 0) |
4203 | goto out; /* F_DUPFD failed */ | 4209 | goto out; /* F_DUPFD failed */ |
4204 | close_on_exec_on(fd); | 4210 | if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */ |
4211 | close_on_exec_on(fd); | ||
4205 | while (1) { /* while we are in the background */ | 4212 | while (1) { /* while we are in the background */ |
4206 | pgrp = tcgetpgrp(fd); | 4213 | pgrp = tcgetpgrp(fd); |
4207 | if (pgrp < 0) { | 4214 | if (pgrp < 0) { |
@@ -5791,13 +5798,14 @@ savefd(int from) | |||
5791 | int newfd; | 5798 | int newfd; |
5792 | int err; | 5799 | int err; |
5793 | 5800 | ||
5794 | newfd = fcntl(from, F_DUPFD, 10); | 5801 | newfd = fcntl(from, F_DUPFD_CLOEXEC, 10); |
5795 | err = newfd < 0 ? errno : 0; | 5802 | err = newfd < 0 ? errno : 0; |
5796 | if (err != EBADF) { | 5803 | if (err != EBADF) { |
5797 | if (err) | 5804 | if (err) |
5798 | ash_msg_and_raise_perror("%d", from); | 5805 | ash_msg_and_raise_perror("%d", from); |
5799 | close(from); | 5806 | close(from); |
5800 | fcntl(newfd, F_SETFD, FD_CLOEXEC); | 5807 | if (F_DUPFD_CLOEXEC == F_DUPFD) |
5808 | close_on_exec_on(newfd); | ||
5801 | } | 5809 | } |
5802 | 5810 | ||
5803 | return newfd; | 5811 | return newfd; |
@@ -5815,12 +5823,15 @@ dup2_or_raise(int from, int to) | |||
5815 | return newfd; | 5823 | return newfd; |
5816 | } | 5824 | } |
5817 | static int | 5825 | static int |
5818 | fcntl_F_DUPFD(int fd, int avoid_fd) | 5826 | dup_CLOEXEC(int fd, int avoid_fd) |
5819 | { | 5827 | { |
5820 | int newfd; | 5828 | int newfd; |
5821 | repeat: | 5829 | repeat: |
5822 | newfd = fcntl(fd, F_DUPFD, avoid_fd + 1); | 5830 | newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1); |
5823 | if (newfd < 0) { | 5831 | if (newfd >= 0) { |
5832 | if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */ | ||
5833 | close_on_exec_on(newfd); | ||
5834 | } else { /* newfd < 0 */ | ||
5824 | if (errno == EBUSY) | 5835 | if (errno == EBUSY) |
5825 | goto repeat; | 5836 | goto repeat; |
5826 | if (errno == EINTR) | 5837 | if (errno == EINTR) |
@@ -5833,7 +5844,7 @@ xdup_CLOEXEC_and_close(int fd, int avoid_fd) | |||
5833 | { | 5844 | { |
5834 | int newfd; | 5845 | int newfd; |
5835 | repeat: | 5846 | repeat: |
5836 | newfd = fcntl(fd, F_DUPFD, avoid_fd + 1); | 5847 | newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1); |
5837 | if (newfd < 0) { | 5848 | if (newfd < 0) { |
5838 | if (errno == EBUSY) | 5849 | if (errno == EBUSY) |
5839 | goto repeat; | 5850 | goto repeat; |
@@ -5844,7 +5855,8 @@ xdup_CLOEXEC_and_close(int fd, int avoid_fd) | |||
5844 | return fd; | 5855 | return fd; |
5845 | ash_msg_and_raise_perror("%d", newfd); | 5856 | ash_msg_and_raise_perror("%d", newfd); |
5846 | } | 5857 | } |
5847 | fcntl(newfd, F_SETFD, FD_CLOEXEC); | 5858 | if (F_DUPFD_CLOEXEC == F_DUPFD) |
5859 | close_on_exec_on(newfd); | ||
5848 | close(fd); | 5860 | close(fd); |
5849 | return newfd; | 5861 | return newfd; |
5850 | } | 5862 | } |
@@ -5936,7 +5948,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq) | |||
5936 | for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) { | 5948 | for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) { |
5937 | /* If we collide with an already moved fd... */ | 5949 | /* If we collide with an already moved fd... */ |
5938 | if (fd == sq->two_fd[i].moved_to) { | 5950 | if (fd == sq->two_fd[i].moved_to) { |
5939 | new_fd = fcntl_F_DUPFD(fd, avoid_fd); | 5951 | new_fd = dup_CLOEXEC(fd, avoid_fd); |
5940 | sq->two_fd[i].moved_to = new_fd; | 5952 | sq->two_fd[i].moved_to = new_fd; |
5941 | TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd)); | 5953 | TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd)); |
5942 | if (new_fd < 0) /* what? */ | 5954 | if (new_fd < 0) /* what? */ |
@@ -5951,7 +5963,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq) | |||
5951 | } | 5963 | } |
5952 | 5964 | ||
5953 | /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */ | 5965 | /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */ |
5954 | new_fd = fcntl_F_DUPFD(fd, avoid_fd); | 5966 | new_fd = dup_CLOEXEC(fd, avoid_fd); |
5955 | TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd)); | 5967 | TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd)); |
5956 | if (new_fd < 0) { | 5968 | if (new_fd < 0) { |
5957 | if (errno != EBADF) | 5969 | if (errno != EBADF) |
@@ -7559,7 +7571,7 @@ varvalue(char *name, int varflags, int flags, int *quotedp) | |||
7559 | case '-': | 7571 | case '-': |
7560 | expdest = makestrspace(NOPTS, expdest); | 7572 | expdest = makestrspace(NOPTS, expdest); |
7561 | for (i = NOPTS - 1; i >= 0; i--) { | 7573 | for (i = NOPTS - 1; i >= 0; i--) { |
7562 | if (optlist[i]) { | 7574 | if (optlist[i] && optletters(i)) { |
7563 | USTPUTC(optletters(i), expdest); | 7575 | USTPUTC(optletters(i), expdest); |
7564 | len++; | 7576 | len++; |
7565 | } | 7577 | } |
@@ -7806,13 +7818,13 @@ hasmeta(const char *p) | |||
7806 | p = strpbrk(p, chars); | 7818 | p = strpbrk(p, chars); |
7807 | if (!p) | 7819 | if (!p) |
7808 | break; | 7820 | break; |
7809 | switch ((unsigned char) *p) { | 7821 | switch ((unsigned char)*p) { |
7810 | case CTLQUOTEMARK: | 7822 | case CTLQUOTEMARK: |
7811 | for (;;) { | 7823 | for (;;) { |
7812 | p++; | 7824 | p++; |
7813 | if (*p == CTLQUOTEMARK) | 7825 | if ((unsigned char)*p == CTLQUOTEMARK) |
7814 | break; | 7826 | break; |
7815 | if (*p == CTLESC) | 7827 | if ((unsigned char)*p == CTLESC) |
7816 | p++; | 7828 | p++; |
7817 | if (*p == '\0') /* huh? */ | 7829 | if (*p == '\0') /* huh? */ |
7818 | return 0; | 7830 | return 0; |
@@ -11262,7 +11274,7 @@ setinputfile(const char *fname, int flags) | |||
11262 | int fd; | 11274 | int fd; |
11263 | 11275 | ||
11264 | INT_OFF; | 11276 | INT_OFF; |
11265 | fd = open(fname, O_RDONLY); | 11277 | fd = open(fname, O_RDONLY | O_CLOEXEC); |
11266 | if (fd < 0) { | 11278 | if (fd < 0) { |
11267 | if (flags & INPUT_NOFILE_OK) | 11279 | if (flags & INPUT_NOFILE_OK) |
11268 | goto out; | 11280 | goto out; |
@@ -11271,8 +11283,9 @@ setinputfile(const char *fname, int flags) | |||
11271 | } | 11283 | } |
11272 | if (fd < 10) | 11284 | if (fd < 10) |
11273 | fd = savefd(fd); | 11285 | fd = savefd(fd); |
11274 | else | 11286 | else if (O_CLOEXEC == 0) /* old libc */ |
11275 | close_on_exec_on(fd); | 11287 | close_on_exec_on(fd); |
11288 | |||
11276 | setinputfd(fd, flags & INPUT_PUSH_FILE); | 11289 | setinputfd(fd, flags & INPUT_PUSH_FILE); |
11277 | out: | 11290 | out: |
11278 | INT_ON; | 11291 | INT_ON; |
@@ -12595,6 +12608,12 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
12595 | break; | 12608 | break; |
12596 | #endif | 12609 | #endif |
12597 | case CBQUOTE: /* '`' */ | 12610 | case CBQUOTE: /* '`' */ |
12611 | if (checkkwd & CHKEOFMARK) { | ||
12612 | quotef = 1; | ||
12613 | USTPUTC('`', out); | ||
12614 | break; | ||
12615 | } | ||
12616 | |||
12598 | PARSEBACKQOLD(); | 12617 | PARSEBACKQOLD(); |
12599 | break; | 12618 | break; |
12600 | case CENDFILE: | 12619 | case CENDFILE: |
@@ -12727,7 +12746,7 @@ parseredir: { | |||
12727 | np = stzalloc(sizeof(struct nfile)); | 12746 | np = stzalloc(sizeof(struct nfile)); |
12728 | if (c == '>') { | 12747 | if (c == '>') { |
12729 | np->nfile.fd = 1; | 12748 | np->nfile.fd = 1; |
12730 | c = pgetc(); | 12749 | c = pgetc_eatbnl(); |
12731 | if (c == '>') | 12750 | if (c == '>') |
12732 | np->type = NAPPEND; | 12751 | np->type = NAPPEND; |
12733 | else if (c == '|') | 12752 | else if (c == '|') |
@@ -12749,7 +12768,7 @@ parseredir: { | |||
12749 | #endif | 12768 | #endif |
12750 | else { /* c == '<' */ | 12769 | else { /* c == '<' */ |
12751 | /*np->nfile.fd = 0; - stzalloc did it */ | 12770 | /*np->nfile.fd = 0; - stzalloc did it */ |
12752 | c = pgetc(); | 12771 | c = pgetc_eatbnl(); |
12753 | switch (c) { | 12772 | switch (c) { |
12754 | case '<': | 12773 | case '<': |
12755 | if (sizeof(struct nfile) != sizeof(struct nhere)) { | 12774 | if (sizeof(struct nfile) != sizeof(struct nhere)) { |
@@ -12759,7 +12778,7 @@ parseredir: { | |||
12759 | np->type = NHERE; | 12778 | np->type = NHERE; |
12760 | heredoc = stzalloc(sizeof(struct heredoc)); | 12779 | heredoc = stzalloc(sizeof(struct heredoc)); |
12761 | heredoc->here = np; | 12780 | heredoc->here = np; |
12762 | c = pgetc(); | 12781 | c = pgetc_eatbnl(); |
12763 | if (c == '-') { | 12782 | if (c == '-') { |
12764 | heredoc->striptabs = 1; | 12783 | heredoc->striptabs = 1; |
12765 | } else { | 12784 | } else { |
@@ -12989,23 +13008,13 @@ parsebackq: { | |||
12989 | int pc; | 13008 | int pc; |
12990 | 13009 | ||
12991 | setprompt_if(needprompt, 2); | 13010 | setprompt_if(needprompt, 2); |
12992 | pc = pgetc(); | 13011 | pc = pgetc_eatbnl(); |
12993 | switch (pc) { | 13012 | switch (pc) { |
12994 | case '`': | 13013 | case '`': |
12995 | goto done; | 13014 | goto done; |
12996 | 13015 | ||
12997 | case '\\': | 13016 | case '\\': |
12998 | pc = pgetc(); | 13017 | pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */ |
12999 | if (pc == '\n') { | ||
13000 | nlprompt(); | ||
13001 | /* | ||
13002 | * If eating a newline, avoid putting | ||
13003 | * the newline into the new character | ||
13004 | * stream (via the STPUTC after the | ||
13005 | * switch). | ||
13006 | */ | ||
13007 | continue; | ||
13008 | } | ||
13009 | if (pc != '\\' && pc != '`' && pc != '$' | 13018 | if (pc != '\\' && pc != '`' && pc != '$' |
13010 | && (!dblquote || pc != '"') | 13019 | && (!dblquote || pc != '"') |
13011 | ) { | 13020 | ) { |
@@ -13137,7 +13146,7 @@ xxreadtoken(void) | |||
13137 | } | 13146 | } |
13138 | setprompt_if(needprompt, 2); | 13147 | setprompt_if(needprompt, 2); |
13139 | for (;;) { /* until token or start of word found */ | 13148 | for (;;) { /* until token or start of word found */ |
13140 | c = pgetc(); | 13149 | c = pgetc_eatbnl(); |
13141 | if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) | 13150 | if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA)) |
13142 | continue; | 13151 | continue; |
13143 | 13152 | ||
@@ -13146,11 +13155,7 @@ xxreadtoken(void) | |||
13146 | continue; | 13155 | continue; |
13147 | pungetc(); | 13156 | pungetc(); |
13148 | } else if (c == '\\') { | 13157 | } else if (c == '\\') { |
13149 | if (pgetc() != '\n') { | 13158 | break; /* return readtoken1(...) */ |
13150 | pungetc(); | ||
13151 | break; /* return readtoken1(...) */ | ||
13152 | } | ||
13153 | nlprompt(); | ||
13154 | } else { | 13159 | } else { |
13155 | const char *p; | 13160 | const char *p; |
13156 | 13161 | ||
@@ -13165,7 +13170,7 @@ xxreadtoken(void) | |||
13165 | break; /* return readtoken1(...) */ | 13170 | break; /* return readtoken1(...) */ |
13166 | 13171 | ||
13167 | if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) { | 13172 | if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) { |
13168 | int cc = pgetc(); | 13173 | int cc = pgetc_eatbnl(); |
13169 | if (cc == c) { /* double occurrence? */ | 13174 | if (cc == c) { /* double occurrence? */ |
13170 | p += xxreadtoken_doubles + 1; | 13175 | p += xxreadtoken_doubles + 1; |
13171 | } else { | 13176 | } else { |
@@ -13197,7 +13202,7 @@ xxreadtoken(void) | |||
13197 | } | 13202 | } |
13198 | setprompt_if(needprompt, 2); | 13203 | setprompt_if(needprompt, 2); |
13199 | for (;;) { /* until token or start of word found */ | 13204 | for (;;) { /* until token or start of word found */ |
13200 | c = pgetc(); | 13205 | c = pgetc_eatbnl(); |
13201 | switch (c) { | 13206 | switch (c) { |
13202 | case ' ': case '\t': | 13207 | case ' ': case '\t': |
13203 | IF_ASH_ALIAS(case PEOA:) | 13208 | IF_ASH_ALIAS(case PEOA:) |
@@ -13207,30 +13212,23 @@ xxreadtoken(void) | |||
13207 | continue; | 13212 | continue; |
13208 | pungetc(); | 13213 | pungetc(); |
13209 | continue; | 13214 | continue; |
13210 | case '\\': | ||
13211 | if (pgetc() == '\n') { | ||
13212 | nlprompt(); | ||
13213 | continue; | ||
13214 | } | ||
13215 | pungetc(); | ||
13216 | goto breakloop; | ||
13217 | case '\n': | 13215 | case '\n': |
13218 | nlnoprompt(); | 13216 | nlnoprompt(); |
13219 | RETURN(TNL); | 13217 | RETURN(TNL); |
13220 | case PEOF: | 13218 | case PEOF: |
13221 | RETURN(TEOF); | 13219 | RETURN(TEOF); |
13222 | case '&': | 13220 | case '&': |
13223 | if (pgetc() == '&') | 13221 | if (pgetc_eatbnl() == '&') |
13224 | RETURN(TAND); | 13222 | RETURN(TAND); |
13225 | pungetc(); | 13223 | pungetc(); |
13226 | RETURN(TBACKGND); | 13224 | RETURN(TBACKGND); |
13227 | case '|': | 13225 | case '|': |
13228 | if (pgetc() == '|') | 13226 | if (pgetc_eatbnl() == '|') |
13229 | RETURN(TOR); | 13227 | RETURN(TOR); |
13230 | pungetc(); | 13228 | pungetc(); |
13231 | RETURN(TPIPE); | 13229 | RETURN(TPIPE); |
13232 | case ';': | 13230 | case ';': |
13233 | if (pgetc() == ';') | 13231 | if (pgetc_eatbnl() == ';') |
13234 | RETURN(TENDCASE); | 13232 | RETURN(TENDCASE); |
13235 | pungetc(); | 13233 | pungetc(); |
13236 | RETURN(TSEMI); | 13234 | RETURN(TSEMI); |
@@ -13238,11 +13236,9 @@ xxreadtoken(void) | |||
13238 | RETURN(TLP); | 13236 | RETURN(TLP); |
13239 | case ')': | 13237 | case ')': |
13240 | RETURN(TRP); | 13238 | RETURN(TRP); |
13241 | default: | ||
13242 | goto breakloop; | ||
13243 | } | 13239 | } |
13240 | break; | ||
13244 | } | 13241 | } |
13245 | breakloop: | ||
13246 | return readtoken1(c, BASESYNTAX, (char *)NULL, 0); | 13242 | return readtoken1(c, BASESYNTAX, (char *)NULL, 0); |
13247 | #undef RETURN | 13243 | #undef RETURN |
13248 | } | 13244 | } |