summaryrefslogtreecommitdiff
path: root/function.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2016-03-19 17:26:08 -0400
committerPaul Smith <psmith@gnu.org>2016-03-21 00:44:53 -0400
commit2b9dd215d588a1b9aa8eaa398e567414afaafce8 (patch)
tree5fa7dd34968fe6c63ef78bcc83aaa795cf1144e5 /function.c
parentfc2ddebdae087dbdd4b0db7654696e1a0e53ebc3 (diff)
* function.c (func_file): Support reading from files.
* NEWS: Add information about reading files. * make.texi (File Function): Describe reading files. * tests/scripts/functions/file: Test new features for $(file ...)
Diffstat (limited to 'function.c')
-rw-r--r--function.c62
1 files changed, 51 insertions, 11 deletions
diff --git a/function.c b/function.c
index 9f9f0fc3..a80f194f 100644
--- a/function.c
+++ b/function.c
@@ -2208,27 +2208,67 @@ func_file (char *o, char **argv, const char *funcname UNUSED)
}
fn = next_token (fn);
- fp = fopen (fn, mode);
+ if (fn[0] == '\0')
+ O (fatal, *expanding_var, _("file: missing filename"));
+
+ ENULLLOOP (fp, fopen (fn, mode));
if (fp == NULL)
- {
- const char *err = strerror (errno);
- OSS (fatal, reading_file, _("open: %s: %s"), fn, err);
- }
+ OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno));
+
if (argv[1])
{
int l = strlen (argv[1]);
int nl = l == 0 || argv[1][l-1] != '\n';
if (fputs (argv[1], fp) == EOF || (nl && fputc ('\n', fp) == EOF))
- {
- const char *err = strerror (errno);
- OSS (fatal, reading_file, _("write: %s: %s"), fn, err);
- }
+ OSS (fatal, reading_file, _("write: %s: %s"), fn, strerror (errno));
+ }
+ if (fclose (fp))
+ OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
+ }
+ else if (fn[0] == '<')
+ {
+ char *preo = o;
+ FILE *fp;
+
+ fn = next_token (++fn);
+ if (fn[0] == '\0')
+ O (fatal, *expanding_var, _("file: missing filename"));
+
+ if (argv[1])
+ O (fatal, *expanding_var, _("file: too many arguments"));
+
+ ENULLLOOP (fp, fopen (fn, "r"));
+ if (fp == NULL)
+ {
+ if (errno == ENOENT)
+ return o;
+ OSS (fatal, reading_file, _("open: %s: %s"), fn, strerror (errno));
}
- fclose (fp);
+
+ while (1)
+ {
+ char buf[1024];
+ size_t l = fread (buf, 1, sizeof (buf), fp);
+ if (l > 0)
+ o = variable_buffer_output (o, buf, l);
+
+ if (ferror (fp))
+ if (errno != EINTR)
+ OSS (fatal, reading_file, _("read: %s: %s"), fn, strerror (errno));
+ if (feof (fp))
+ break;
+ }
+ if (fclose (fp))
+ OSS (fatal, reading_file, _("close: %s: %s"), fn, strerror (errno));
+
+ /* Remove trailing newline. */
+ if (o > preo && o[-1] == '\n')
+ if (--o > preo && o[-1] == '\r')
+ --o;
}
else
- OS (fatal, reading_file, _("Invalid file operation: %s"), fn);
+ OS (fatal, *expanding_var, _("file: invalid file operation: %s"), fn);
return o;
}