diff --git a/src/dhcpd-pools.c b/src/dhcpd-pools.c index 98eba2f..6488657 100644 --- a/src/dhcpd-pools.c +++ b/src/dhcpd-pools.c @@ -77,6 +77,8 @@ int main(int argc, char **argv) {NULL, 0, NULL, 0} }; + atexit(close_stdout); + /* FIXME: make these allocations dynamic up on need. */ config.dhcpdconf_file = safe_malloc(sizeof(char) * MAXLEN); config.dhcpdlease_file = safe_malloc(sizeof(char) * MAXLEN); diff --git a/src/dhcpd-pools.h b/src/dhcpd-pools.h index 6d6fc9f..e97263d 100644 --- a/src/dhcpd-pools.h +++ b/src/dhcpd-pools.h @@ -39,6 +39,7 @@ #include #include #include +#include /* Feature test switches */ #define _POSIX_SOURCE 1 @@ -167,6 +168,8 @@ void *safe_malloc(const size_t size) void *safe_realloc(void *__restrict ptr, const size_t size); char *safe_strdup(const char *__restrict str) __attribute__ ((nonnull(1))); int xstrstr(char *__restrict a, char *__restrict b, int len); +int close_stream(FILE * stream); +void close_stdout(void); void print_version(void) __attribute__ ((noreturn)); void usage(int status) __attribute__ ((noreturn)); /* qsort required functions... */ diff --git a/src/other.c b/src/other.c index 9952f72..f27af70 100644 --- a/src/other.c +++ b/src/other.c @@ -42,6 +42,7 @@ #else extern void exit(); extern char *malloc(); +extern void _exit(); #endif #ifdef HAVE_STRING_H @@ -52,9 +53,12 @@ extern char *malloc(); #include #include +#include #include #include #include +#include +#include /* Simple memory allocation wrapper */ void *safe_malloc(const size_t size) @@ -150,6 +154,32 @@ void clean_up(void) free(shared_networks); } +int close_stream(FILE * stream) +{ + const int some_pending = (__fpending(stream) != 0); + const int prev_fail = (ferror(stream) != 0); + const int fclose_fail = (fclose(stream) != 0); + if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) { + if (!fclose_fail) + errno = 0; + return EOF; + } + return 0; +} + +/* Use atexit(); */ +void close_stdout(void) +{ + if (close_stream(stdout) != 0 && !(errno == EPIPE)) { + char const *write_error = "write error"; + error(0, errno, "%s", write_error); + _exit(EXIT_FAILURE); + } + + if (close_stream(stderr) != 0) + _exit(EXIT_FAILURE); +} + void __attribute__ ((__noreturn__)) print_version(void) { fprintf(stdout, "%s\n" diff --git a/src/output.c b/src/output.c index 4ef5e66..7e03bf5 100644 --- a/src/output.c +++ b/src/output.c @@ -197,7 +197,7 @@ int output_txt(void) warn("output_txt: fflush"); } } else { - ret = fclose(outfile); + ret = close_stream(outfile); if (ret) { warn("output_txt: fclose"); } @@ -304,7 +304,7 @@ int output_xml(void) warn("output_xml: fflush"); } } else { - ret = fclose(outfile); + ret = close_stream(outfile); if (ret) { warn("output_xml: fclose"); } @@ -633,7 +633,7 @@ int output_html(void) warn("output_html: fflush"); } } else { - ret = fclose(outfile); + ret = close_stream(outfile); if (ret) { warn("output_html: fclose"); } @@ -781,7 +781,7 @@ int output_csv(void) warn("output_cvs: fflush"); } } else { - ret = fclose(outfile); + ret = close_stream(outfile); if (ret) { warn("output_cvs: fclose"); }