[tz] [PROPOSED PATCH 2/3] zdump: check more consistently for output errors

Paul Eggert eggert at cs.ucla.edu
Tue Aug 19 06:27:25 UTC 2014


* zdump.c: Include <errno.h>.
(errout): New static var.
(my_localtime) [!TYPECHECK]
(abbrok): Set it.
(close_file): New function.
(usage, main): Use it.
(main): Prefer 'return X;' to 'exit(X);'.
Check for stderr output error.
---
 zdump.c | 41 ++++++++++++++++++++++++++++-------------
 1 file changed, 28 insertions(+), 13 deletions(-)

diff --git a/zdump.c b/zdump.c
index cdcde5a..e9a42fd 100644
--- a/zdump.c
+++ b/zdump.c
@@ -24,6 +24,7 @@
 #include "time.h"	/* for struct tm */
 #include "stdlib.h"	/* for exit, malloc, atoi */
 #include "limits.h"	/* for CHAR_BIT, LLONG_MAX */
+#include <errno.h>
 
 /*
 ** Substitutes for pre-C99 compilers.
@@ -206,6 +207,7 @@ static time_t const absolute_max_time =
 static size_t	longest;
 static char *	progname;
 static int	warned;
+static int	errout;
 
 static char *abbr(struct tm *);
 static intmax_t	delta(struct tm *, struct tm *) ATTRIBUTE_PURE;
@@ -264,6 +266,7 @@ my_localtime(time_t *tp)
 			fprintf(stderr, " -> ");
 			fprintf(stderr, tformat(), t);
 			fprintf(stderr, "\n");
+			errout = TRUE;
 		}
 	}
 	return tmp;
@@ -302,7 +305,21 @@ abbrok(const char *const abbrp, const char *const zone)
 	fprintf(stderr,
 		_("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"),
 		progname, zone, abbrp, wp);
-	warned = TRUE;
+	warned = errout = TRUE;
+}
+
+static void
+close_file(FILE *stream, char const *name)
+{
+  char const *e = (ferror(stream) ? _("I/O error")
+		   : fclose(stream) != 0 ? strerror(errno) : NULL);
+  if (e) {
+    fprintf(stderr, "%s: ", progname);
+    if (name)
+      fprintf(stderr, "%s: ", name);
+    fprintf(stderr, "%s\n", e);
+    exit(EXIT_FAILURE);
+  }
 }
 
 static void
@@ -313,6 +330,8 @@ _("%s: usage: %s [--version] [--help] [-{vV}] [-{ct} [lo,]hi] zonename ...\n"
   "\n"
   "Report bugs to %s.\n"),
 		       progname, progname, REPORT_BUGS_TO);
+	if (status == EXIT_SUCCESS)
+	  close_file(stream, NULL);
 	exit(status);
 }
 
@@ -348,7 +367,7 @@ main(int argc, char *argv[])
 	for (i = 1; i < argc; ++i)
 		if (strcmp(argv[i], "--version") == 0) {
 			printf("zdump %s%s\n", PKGVERSION, TZVERSION);
-			exit(EXIT_SUCCESS);
+			return EXIT_SUCCESS;
 		} else if (strcmp(argv[i], "--help") == 0) {
 			usage(stdout, EXIT_SUCCESS);
 		}
@@ -388,7 +407,7 @@ main(int argc, char *argv[])
 			} else {
 				fprintf(stderr, _("%s: wild -c argument %s\n"),
 					progname, cutarg);
-				exit(EXIT_FAILURE);
+				return EXIT_FAILURE;
 			}
 		}
 		if (cutarg != NULL || cuttimes == NULL) {
@@ -421,7 +440,7 @@ main(int argc, char *argv[])
 				fprintf(stderr,
 					_("%s: wild -t argument %s\n"),
 					progname, cuttimes);
-				exit(EXIT_FAILURE);
+				return EXIT_FAILURE;
 			}
 		}
 	}
@@ -440,7 +459,7 @@ main(int argc, char *argv[])
 		if (fakeenv == NULL
 		    || (fakeenv[0] = malloc(longest + 4)) == NULL) {
 		  perror(progname);
-		  exit(EXIT_FAILURE);
+		  return EXIT_FAILURE;
 		}
 		to = 0;
 		strcpy(fakeenv[to++], "TZ=");
@@ -506,14 +525,10 @@ main(int argc, char *argv[])
 			show(argv[i], t, TRUE);
 		}
 	}
-	if (fflush(stdout) || ferror(stdout)) {
-		fprintf(stderr, "%s: ", progname);
-		perror(_("Error writing to standard output"));
-		exit(EXIT_FAILURE);
-	}
-	exit(EXIT_SUCCESS);
-	/* If exit fails to exit... */
-	return EXIT_FAILURE;
+	close_file(stdout, NULL);
+	if (errout && (ferror(stderr) || fclose(stderr) != 0))
+	  return EXIT_FAILURE;
+	return EXIT_SUCCESS;
 }
 
 static time_t
-- 
1.9.1



More information about the tz mailing list