summaryrefslogtreecommitdiffstats
path: root/bin/sh/redir.c
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2013-04-02 21:34:38 +0000
committerjilles <jilles@FreeBSD.org>2013-04-02 21:34:38 +0000
commit7236eb0dda54324c7d5909c8f01ef2aaaefb3e30 (patch)
tree8f6ca9e8c37ed97b49f6b76f25dccfd5da809069 /bin/sh/redir.c
parente2bb503df79b3a278b60540c030abad3cc7817e4 (diff)
downloadFreeBSD-src-7236eb0dda54324c7d5909c8f01ef2aaaefb3e30.zip
FreeBSD-src-7236eb0dda54324c7d5909c8f01ef2aaaefb3e30.tar.gz
sh: Write as much into the heredoc pipe as possible, to avoid forking.
Use non-blocking I/O to write as much as the pipe will accept (often 64K, but it can be as little as 4K), avoiding the need for the ugly PIPESIZE constant. If PIPESIZE was set too high, a deadlock would occur.
Diffstat (limited to 'bin/sh/redir.c')
-rw-r--r--bin/sh/redir.c18
1 files changed, 13 insertions, 5 deletions
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:
OpenPOWER on IntegriCloud