summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--modules/gnu.c24
2 files changed, 25 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 3f98309c..51fda555 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2009-02-18 Eric Blake <ebb9@byu.net>
+ Speed up esyscmd with buffer reads.
+ * modules/gnu.c (esyscmd): Read blocks directly into obstack,
+ rather than repeatedly reading bytes. Detect read errors.
+
Avoid risk of stack overflow.
* m4/output.c (insert_file): Avoid stack allocation of large
buffer.
diff --git a/modules/gnu.c b/modules/gnu.c
index f44f0ba4..e6c7691e 100644
--- a/modules/gnu.c
+++ b/modules/gnu.c
@@ -654,7 +654,6 @@ M4BUILTIN_HANDLER (esyscmd)
if (m4_set_sysval && m4_sysval_flush)
{
FILE *pin;
- int ch;
if (m4_get_safer_opt (context))
{
@@ -684,8 +683,27 @@ M4BUILTIN_HANDLER (esyscmd)
}
else
{
- while ((ch = getc (pin)) != EOF)
- obstack_1grow (obs, ch);
+ while (1)
+ {
+ size_t avail = obstack_room (obs);
+ if (!avail)
+ {
+ int ch = getc (pin);
+ if (ch == EOF)
+ break;
+ obstack_1grow (obs, ch);
+ }
+ else
+ {
+ size_t len = fread (obstack_next_free (obs), 1, avail, pin);
+ if (len <= 0)
+ break;
+ obstack_blank_fast (obs, len);
+ }
+ }
+ if (ferror (pin))
+ m4_warn (context, errno, me, _("cannot read pipe to command %s"),
+ quotearg_style (locale_quoting_style, cmd));
m4_set_sysval (pclose (pin));
}
}