summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2021-12-01 22:46:18 +0200
committerArnold D. Robbins <arnold@skeeve.com>2021-12-01 22:46:18 +0200
commit0521e672efdbfdaedabfacca03c7a535b4f8526c (patch)
tree96c5db398195d2b81d66a891fae0848b97bfe87d
parenta22095c81a677b82accccb53cab91052cdc0cbfe (diff)
parentf77e1318c515d495ac9c08bdfdf2dadf79a9649f (diff)
downloadgawk-0521e672efdbfdaedabfacca03c7a535b4f8526c.tar.gz
Merge branch 'gawk-5.1-stable'
-rw-r--r--ChangeLog33
-rw-r--r--awk.h2
-rw-r--r--builtin.c77
-rw-r--r--io.c21
-rw-r--r--main.c12
-rw-r--r--nonposix.h1
-rw-r--r--pc/ChangeLog5
-rw-r--r--pc/gawkmisc.pc38
-rw-r--r--posix/ChangeLog4
-rw-r--r--posix/gawkmisc.c5
-rw-r--r--vms/ChangeLog4
-rw-r--r--vms/gawkmisc.vms5
12 files changed, 135 insertions, 72 deletions
diff --git a/ChangeLog b/ChangeLog
index 34d3110d..333e026d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2021-12-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ * builtin.c (efflush): Don't use return in call of function
+ returning void. It works, but is funky, and I think some
+ compilers will complain.
+
+ Unrelated. Clean up the calls to w32_maybe_set_errno.
+
+ * awk.h (os_maybe_set_errno): Add declaration.
+ * builtin.c (wrerror): Replaced ifdef'ed code calling
+ w32_maybe_set_errno() with simple call to os_maybe_set_errno().
+ * io.c (non_fatal_flush_std_file, close_io): Ditto.
+ * main.c (usage, copyleft): Ditto.
+ * nonposix.h (w32_maybe_set_errno): Remove declaration.
+
+2021-11-30 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ Improve output redirection error handling for problems not detected
+ until the final flush or close. Thanks to Miguel Pineiro Jr.
+ <mpj@pineiro.cc> for the bug report and suggesting a fix.
+
+ * awk.h (efflush): Add declaration.
+ * builtin.c (efwrite): Break up into 3 functions by moving the
+ flushing logic into efflush and the error handling logic into
+ wrerror.
+ (wrerror): New function containing the error-handling logic extracted
+ from efwrite.
+ (efflush): New function containing the fflush logic extracted from
+ efwrite.
+ * io.c (close_redir): Call efflush prior to closing the redirection
+ to identify any problems with flushing output and to take advantage
+ of the error-handling logic used for print and printf.
+
2021-11-21 Arnold D. Robbins <arnold@skeeve.com>
* builtin.c (do_typeof): Make Node_array_ref handling smarter.
diff --git a/awk.h b/awk.h
index 9e6f2ca1..581b977e 100644
--- a/awk.h
+++ b/awk.h
@@ -1469,6 +1469,7 @@ extern bool is_identchar(int c);
extern NODE *make_regnode(NODETYPE type, NODE *exp);
extern bool validate_qualified_name(char *token);
/* builtin.c */
+extern void efflush(FILE *fp, const char *from, struct redirect *rp);
extern double double_to_int(double d);
extern NODE *do_exp(int nargs);
extern NODE *do_fflush(int nargs);
@@ -1621,6 +1622,7 @@ extern int os_isreadable(const awk_input_buf_t *iobuf, bool *isdir);
extern int os_is_setuid(void);
extern int os_setbinmode(int fd, int mode);
extern void os_restore_mode(int fd);
+extern void os_maybe_set_errno(void);
extern size_t optimal_bufsize(int fd, struct stat *sbuf);
extern int ispath(const char *file);
extern int isdirpunct(int c);
diff --git a/builtin.c b/builtin.c
index 386b6ed4..37cc5728 100644
--- a/builtin.c
+++ b/builtin.c
@@ -96,43 +96,14 @@ fatal(_("attempt to use array `%s' in a scalar context"), array_vname(s1)); \
*/
#define GAWK_RANDOM_MAX 0x7fffffffL
-/* efwrite --- like fwrite, but with error checking */
+
+/* wrerror --- handle a write or flush error */
static void
-efwrite(const void *ptr,
- size_t size,
- size_t count,
- FILE *fp,
- const char *from,
- struct redirect *rp,
- bool flush)
+wrerror(FILE *fp, const char *from, struct redirect *rp)
{
- errno = 0;
- if (rp != NULL) {
- if (rp->output.gawk_fwrite(ptr, size, count, fp, rp->output.opaque) != count)
- goto wrerror;
- } else if (fwrite(ptr, size, count, fp) != count)
- goto wrerror;
- if (flush
- && ((fp == stdout && output_is_tty)
- || (rp != NULL && (rp->flag & RED_NOBUF) != 0))) {
- if (rp != NULL) {
- rp->output.gawk_fflush(fp, rp->output.opaque);
- if (rp->output.gawk_ferror(fp, rp->output.opaque))
- goto wrerror;
- } else {
- fflush(fp);
- if (ferror(fp))
- goto wrerror;
- }
- }
- return;
+ os_maybe_set_errno();
-wrerror:
-#ifdef __MINGW32__
- if (errno == 0 || errno == EINVAL)
- w32_maybe_set_errno();
-#endif
/* for stdout, die with a real SIGPIPE, like other awks */
if (fp == stdout && errno == EPIPE)
die_via_sigpipe();
@@ -150,6 +121,46 @@ wrerror:
errno ? strerror(errno) : _("reason unknown"));
}
+/* efflush --- flush output with proper error handling */
+
+void
+efflush(FILE *fp, const char *from, struct redirect *rp)
+{
+ errno = 0;
+ if (rp != NULL) {
+ rp->output.gawk_fflush(fp, rp->output.opaque);
+ if (rp->output.gawk_ferror(fp, rp->output.opaque))
+ wrerror(fp, from, rp);
+ } else {
+ fflush(fp);
+ if (ferror(fp))
+ wrerror(fp, from, rp);
+ }
+}
+
+/* efwrite --- like fwrite, but with error checking */
+
+static void
+efwrite(const void *ptr,
+ size_t size,
+ size_t count,
+ FILE *fp,
+ const char *from,
+ struct redirect *rp,
+ bool flush)
+{
+ errno = 0;
+ if (rp != NULL) {
+ if (rp->output.gawk_fwrite(ptr, size, count, fp, rp->output.opaque) != count)
+ return wrerror(fp, from, rp);
+ } else if (fwrite(ptr, size, count, fp) != count)
+ return wrerror(fp, from, rp);
+ if (flush
+ && ((fp == stdout && output_is_tty)
+ || (rp != NULL && (rp->flag & RED_NOBUF) != 0)))
+ efflush(fp, from, rp);
+}
+
/* do_exp --- exponential function */
NODE *
diff --git a/io.c b/io.c
index 91c94d9b..0da8699e 100644
--- a/io.c
+++ b/io.c
@@ -1375,6 +1375,9 @@ close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how)
if (rp == NULL)
return 0;
+ if ((rp->flag & RED_WRITE) && rp->output.fp)
+ /* flush before closing to leverage special error handling */
+ efflush(rp->output.fp, "flush", rp);
if (rp->output.fp == stdout || rp->output.fp == stderr)
goto checkwarn; /* bypass closing, remove from list */
@@ -1460,10 +1463,8 @@ non_fatal_flush_std_file(FILE *fp)
bool is_fatal = ! is_non_fatal_std(fp);
if (is_fatal) {
-#ifdef __MINGW32__
- if (errno == 0 || errno == EINVAL)
- w32_maybe_set_errno();
-#endif
+ os_maybe_set_errno();
+
if (errno == EPIPE)
die_via_sigpipe();
else
@@ -1560,10 +1561,8 @@ close_io(bool *stdio_problem, bool *got_EPIPE)
*stdio_problem = false;
/* we don't warn about stdout/stderr if EPIPE, but we do error exit */
if (fflush(stdout) != 0) {
-#ifdef __MINGW32__
- if (errno == 0 || errno == EINVAL)
- w32_maybe_set_errno();
-#endif
+ os_maybe_set_errno();
+
if (errno != EPIPE)
warning(_("error writing standard output: %s"), strerror(errno));
else
@@ -1573,10 +1572,8 @@ close_io(bool *stdio_problem, bool *got_EPIPE)
*stdio_problem = true;
}
if (fflush(stderr) != 0) {
-#ifdef __MINGW32__
- if (errno == 0 || errno == EINVAL)
- w32_maybe_set_errno();
-#endif
+ os_maybe_set_errno();
+
if (errno != EPIPE)
warning(_("error writing standard error: %s"), strerror(errno));
else
diff --git a/main.c b/main.c
index fae3b3a9..2ca0dc85 100644
--- a/main.c
+++ b/main.c
@@ -654,10 +654,8 @@ By default it reads standard input and writes standard output.\n\n"), fp);
fflush(fp);
if (ferror(fp)) {
-#ifdef __MINGW32__
- if (errno == 0 || errno == EINVAL)
- w32_maybe_set_errno();
-#endif
+ os_maybe_set_errno();
+
/* don't warn about stdout/stderr if EPIPE, but do error exit */
if (errno == EPIPE)
die_via_sigpipe();
@@ -704,10 +702,8 @@ along with this program. If not, see http://www.gnu.org/licenses/.\n");
fflush(stdout);
if (ferror(stdout)) {
-#ifdef __MINGW32__
- if (errno == 0 || errno == EINVAL)
- w32_maybe_set_errno();
-#endif
+ os_maybe_set_errno();
+
/* don't warn about stdout if EPIPE, but do error exit */
if (errno != EPIPE)
warning(_("error writing standard output: %s"), strerror(errno));
diff --git a/nonposix.h b/nonposix.h
index 35359abf..b975f75e 100644
--- a/nonposix.h
+++ b/nonposix.h
@@ -56,7 +56,6 @@ unsigned int getegid (void);
/* gawkmisc.pc */
int unsetenv (const char *);
int setenv (const char *, const char *, int);
-void w32_maybe_set_errno (void);
char *w32_setlocale (int, const char *);
/* libintl.h from GNU gettext defines setlocale to redirect that to
its own function. Note: this will have to be revisited if MinGW
diff --git a/pc/ChangeLog b/pc/ChangeLog
index c0027c38..d1acbf50 100644
--- a/pc/ChangeLog
+++ b/pc/ChangeLog
@@ -1,3 +1,8 @@
+2021-12-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawkmisc.pc (os_maybe_set_errno): Renamed from
+ w32_maybe_set_errno. Add check for errno values.
+
2021-11-21 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.tst: Regenerated.
diff --git a/pc/gawkmisc.pc b/pc/gawkmisc.pc
index 1843a168..149ea62c 100644
--- a/pc/gawkmisc.pc
+++ b/pc/gawkmisc.pc
@@ -1066,25 +1066,27 @@ w32_status_to_termsig (unsigned status)
}
void
-w32_maybe_set_errno (void)
+os_maybe_set_errno (void)
{
- DWORD w32err = GetLastError ();
-
- switch (w32err)
- {
- /* When stdout is redirected to a pipe, and the program that
- reads the pipe (e.g., a pager) exits, Windows doesn't set
- errno to a useful value. Help it DTRT. */
- case ERROR_BAD_PIPE:
- case ERROR_PIPE_BUSY:
- case ERROR_NO_DATA:
- case ERROR_PIPE_NOT_CONNECTED:
- errno = EPIPE;
- break;
- default:
- errno = EINVAL;
- break;
- }
+ if (errno == 0 || errno == EINVAL) {
+ DWORD w32err = GetLastError ();
+
+ switch (w32err)
+ {
+ /* When stdout is redirected to a pipe, and the program that
+ reads the pipe (e.g., a pager) exits, Windows doesn't set
+ errno to a useful value. Help it DTRT. */
+ case ERROR_BAD_PIPE:
+ case ERROR_PIPE_BUSY:
+ case ERROR_NO_DATA:
+ case ERROR_PIPE_NOT_CONNECTED:
+ errno = EPIPE;
+ break;
+ default:
+ errno = EINVAL;
+ break;
+ }
+ }
}
#endif /* __MINGW32__ */
diff --git a/posix/ChangeLog b/posix/ChangeLog
index 0553a19f..06b16f74 100644
--- a/posix/ChangeLog
+++ b/posix/ChangeLog
@@ -1,3 +1,7 @@
+2021-12-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawkmisc.c (os_maybe_set_errno): New, empty function.
+
2021-10-27 Arnold D. Robbins <arnold@skeeve.com>
* 5.1.1: Release tar ball made.
diff --git a/posix/gawkmisc.c b/posix/gawkmisc.c
index 10c543ca..e6f316c9 100644
--- a/posix/gawkmisc.c
+++ b/posix/gawkmisc.c
@@ -290,6 +290,11 @@ init_sockets(void)
{
}
+void
+os_maybe_set_errno(void)
+{
+}
+
// For MSYS, restore behavior of working in text mode.
#ifdef __MSYS__
void
diff --git a/vms/ChangeLog b/vms/ChangeLog
index fa2a0fba..1f332f57 100644
--- a/vms/ChangeLog
+++ b/vms/ChangeLog
@@ -1,3 +1,7 @@
+2021-12-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawkmisc.vms (os_maybe_set_errno): New, empty function.
+
2021-10-27 Arnold D. Robbins <arnold@skeeve.com>
* 5.1.1: Release tar ball made.
diff --git a/vms/gawkmisc.vms b/vms/gawkmisc.vms
index c4a2f086..23246bd8 100644
--- a/vms/gawkmisc.vms
+++ b/vms/gawkmisc.vms
@@ -660,3 +660,8 @@ void
init_sockets(void)
{
}
+
+void
+os_maybe_set_errno(void)
+{
+}