[hackers] [sbase] Add *fshut() functions to properly flush file streams || FRIGN

From: <git_AT_suckless.org>
Date: Sun, 5 Apr 2015 10:14:04 +0200 (CEST)

commit 11e2d472bf7ef8e6752ae995a4954d9359c11fdd
Author: FRIGN <dev_AT_frign.de>
Date: Sat Apr 4 21:25:17 2015 +0200

    Add *fshut() functions to properly flush file streams
    
    This has been a known issue for a long time. Example:
    
    printf "word" > /dev/full
    
    wouldn't report there's not enough space on the device.
    This is due to the fact that every libc has internal buffers
    for stdout which store fragments of written data until they reach
    a certain size or on some callback to flush them all at once to the
    kernel.
    You can force the libc to flush them with fflush(). In case flushing
    fails, you can check the return value of fflush() and report an error.
    
    However, previously, sbase didn't have such checks and without fflush(),
    the libc silently flushes the buffers on exit without checking the errors.
    No offense, but there's no way for the libc to report errors in the exit-
    condition.
    
    GNU coreutils solve this by having onexit-callbacks to handle the flushing
    and report issues, but they have obvious deficiencies.
    After long discussions on IRC, we came to the conclusion that checking the
    return value of every io-function would be a bit too much, and having a
    general-purpose fclose-wrapper would be the best way to go.
    
    It turned out that fclose() alone is not enough to detect errors. The right
    way to do it is to fflush() + check ferror on the fp and then to a fclose().
    This is what fshut does and that's how it's done before each return.
    The return value is obviously affected, reporting an error in case a flush
    or close failed, but also when reading failed for some reason, the error-
    state is caught.
    
    the !!( ... + ...) construction is used to call all functions inside the
    brackets and not "terminating" on the first.
    We want errors to be reported, but there's no reason to stop flushing buffers
    when one other file buffer has issues.
    Obviously, functionales come before the flush and ret-logic comes after to
    prevent early exits as well without reporting warnings if there are any.
    
    One more advantage of fshut() is that it is even able to report errors
    on obscure NFS-setups which the other coreutils are unable to detect,
    because they only check the return-value of fflush() and fclose(),
    not ferror() as well.

diff --git a/Makefile b/Makefile
index b9d6e7c..d782193 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -50,6 +50,7 @@ LIBUTILSRC =\
         libutil/eregcomp.c\
         libutil/estrtod.c\
         libutil/fnck.c\
+ libutil/fshut.c\
         libutil/getlines.c\
         libutil/human.c\
         libutil/md5.c\
diff --git a/basename.c b/basename.c
index 3e74590..bb5eaa4 100644
--- a/basename.c
+++ b/basename.c
_AT_@ -33,5 +33,5 @@ main(int argc, char *argv[])
         }
         puts(p);
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/cal.c b/cal.c
index e5f7b56..732917d 100644
--- a/cal.c
+++ b/cal.c
_AT_@ -208,5 +208,5 @@ main(int argc, char *argv[])
 
         drawcal(year, month - 1, ncols, nmons, fday);
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/cat.c b/cat.c
index b50380c..d363bec 100644
--- a/cat.c
+++ b/cat.c
_AT_@ -36,10 +36,12 @@ main(int argc, char *argv[])
                                 ret = 1;
                         } else {
                                 concat(fp, *argv, stdout, "<stdout>");
- fclose(fp);
+ if (fshut(fp, *argv)) {
+ ret = 1;
+ }
                         }
                 }
         }
 
- return ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/cksum.c b/cksum.c
index e931c6e..b2a95b4 100644
--- a/cksum.c
+++ b/cksum.c
_AT_@ -111,9 +111,11 @@ main(int argc, char *argv[])
                                 continue;
                         }
                         cksum(fp, *argv);
- fclose(fp);
+ if (fshut(fp, *argv)) {
+ ret = 1;
+ }
                 }
         }
 
- return ret;
+ return fshut(stdout, "<stdout>") || ret;
 }
diff --git a/cmp.c b/cmp.c
index 685dd26..47ea1e4 100644
--- a/cmp.c
+++ b/cmp.c
_AT_@ -71,5 +71,9 @@ main(int argc, char *argv[])
                 }
         }
 
+ enfshut(2, fp[0], argv[0]);
+ if (fp[0] != fp[1])
+ enfshut(2, fp[1], argv[1]);
+ enfshut(2, stdout, "<stdout>");
         return !same;
 }
diff --git a/col.c b/col.c
index 41a01d5..358d4a8 100644
--- a/col.c
+++ b/col.c
_AT_@ -217,5 +217,5 @@ main(int argc, char *argv[])
         col();
         flush();
 
- return 0;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
 }
diff --git a/cols.c b/cols.c
index 2833e2f..c4c3b91 100644
--- a/cols.c
+++ b/cols.c
_AT_@ -25,7 +25,7 @@ main(int argc, char *argv[])
         struct winsize w;
         struct linebuf b = EMPTY_LINEBUF;
         size_t chars = 65, maxlen = 0, i, j, k, len, bytes, cols, rows;
- int cflag = 0;
+ int cflag = 0, ret = 0;
         char *p;
 
         ARGBEGIN {
_AT_@ -50,10 +50,12 @@ main(int argc, char *argv[])
                 for (; *argv; argc--, argv++) {
                         if (!(fp = fopen(*argv, "r"))) {
                                 weprintf("fopen %s:", *argv);
+ ret = 1;
                                 continue;
                         }
                         getlines(fp, &b);
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
                 }
         }
 
_AT_@ -82,5 +84,5 @@ main(int argc, char *argv[])
                 putchar('\n');
         }
 
- return 0;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/comm.c b/comm.c
index ee79047..4464c43 100644
--- a/comm.c
+++ b/comm.c
_AT_@ -76,8 +76,9 @@ main(int argc, char *argv[])
                 }
                 diff = strcmp(line[0], line[1]);
                 LIMIT(diff, -1, 1);
- printline((2-diff) % 3, line[MAX(0, diff)]);
+ printline((2 - diff) % 3, line[MAX(0, diff)]);
         }
 end:
- return 0;
+ return !!(fshut(fp[0], argv[0]) + (fp[0] != fp[1] && fshut(fp[1], argv[1])) +
+ fshut(stdout, "<stdout>"));
 }
diff --git a/config.mk b/config.mk
index 8d4dbe3..ba43212 100644
--- a/config.mk
+++ b/config.mk
_AT_@ -11,6 +11,6 @@ AR = ar
 RANLIB = ranlib
 
 # For NetBSD add -D_NETBSD_SOURCE
-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700
+CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -DDEBUG
 CFLAGS = -std=c99 -Wall -pedantic
 LDFLAGS = -s # -lrt
diff --git a/cp.c b/cp.c
index ebc3566..ded0122 100644
--- a/cp.c
+++ b/cp.c
_AT_@ -53,5 +53,5 @@ main(int argc, char *argv[])
         }
         enmasse(argc, argv, cp);
 
- return cp_status;
+ return fshut(stdout, "<stdout>") || cp_status;
 }
diff --git a/cut.c b/cut.c
index 7c806af..07faf21 100644
--- a/cut.c
+++ b/cut.c
_AT_@ -196,10 +196,11 @@ main(int argc, char *argv[])
                                         continue;
                                 }
                                 cut(fp, *argv);
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
                         }
                 }
         }
 
- return ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/date.c b/date.c
index a3cd313..f6581d5 100644
--- a/date.c
+++ b/date.c
_AT_@ -45,5 +45,5 @@ main(int argc, char *argv[])
         strftime(buf, sizeof(buf), fmt, now);
         puts(buf);
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/dirname.c b/dirname.c
index 501e5a0..4542199 100644
--- a/dirname.c
+++ b/dirname.c
_AT_@ -23,5 +23,5 @@ main(int argc, char *argv[])
 
         puts(dirname(argv[0]));
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/du.c b/du.c
index 0bc732b..086c9b8 100644
--- a/du.c
+++ b/du.c
_AT_@ -108,5 +108,5 @@ main(int argc, char *argv[])
                 }
         }
 
- return recurse_status;
+ return fshut(stdout, "<stdout>") || recurse_status;
 }
diff --git a/echo.c b/echo.c
index c845c47..44941d1 100644
--- a/echo.c
+++ b/echo.c
_AT_@ -18,5 +18,5 @@ main(int argc, char *argv[])
         if (!nflag)
                 putchar('\n');
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/env.c b/env.c
index 5af93e0..72d078f 100644
--- a/env.c
+++ b/env.c
_AT_@ -45,5 +45,5 @@ main(int argc, char *argv[])
         for (; environ && *environ; environ++)
                 puts(*environ);
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/expand.c b/expand.c
index 506039d..8e6afe1 100644
--- a/expand.c
+++ b/expand.c
_AT_@ -116,9 +116,10 @@ main(int argc, char *argv[])
                                 continue;
                         }
                         expand(*argv, fp);
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
                 }
         }
 
- return ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/expr.c b/expr.c
index e9b794f..b1995c1 100644
--- a/expr.c
+++ b/expr.c
_AT_@ -266,5 +266,6 @@ main(int argc, char *argv[])
                 usage();
         } ARGEND;
 
+ enfshut(3, stdout, "<stdout>");
         return !parse(argv, argc);
 }
diff --git a/find.c b/find.c
index b0f8a93..55d4fef 100644
--- a/find.c
+++ b/find.c
_AT_@ -1036,5 +1036,5 @@ main(int argc, char **argv)
                         t->u.pinfo->freearg(t->extra);
         free(toks);
 
- return gflags.ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || gflags.ret;
 }
diff --git a/fold.c b/fold.c
index 6a52466..e896527 100644
--- a/fold.c
+++ b/fold.c
_AT_@ -100,10 +100,11 @@ main(int argc, char *argv[])
                                 ret = 1;
                         } else {
                                 fold(fp, *argv);
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
                         }
                 }
         }
 
- return ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/grep.c b/grep.c
index 1267055..bf162ae 100644
--- a/grep.c
+++ b/grep.c
_AT_@ -196,7 +196,7 @@ main(int argc, char *argv[])
                 if (!(fp = fmemopen(arg, strlen(arg) + 1, "r")))
                         eprintf("fmemopen:");
                 addpatternfile(fp);
- fclose(fp);
+ efshut(fp, arg);
                 eflag = 1;
                 break;
         case 'f':
_AT_@ -205,7 +205,7 @@ main(int argc, char *argv[])
                 if (!fp)
                         enprintf(Error, "fopen %s:", arg);
                 addpatternfile(fp);
- fclose(fp);
+ efshut(fp, arg);
                 fflag = 1;
                 break;
         case 'h':
_AT_@ -246,7 +246,7 @@ main(int argc, char *argv[])
                 if (!(fp = fmemopen(argv[0], strlen(argv[0]) + 1, "r")))
                         eprintf("fmemopen:");
                 addpatternfile(fp);
- fclose(fp);
+ efshut(fp, argv[0]);
                 argc--;
                 argv++;
         }
_AT_@ -269,8 +269,12 @@ main(int argc, char *argv[])
                         m = grep(fp, argv[i]);
                         if (m == Error || (match != Error && m == Match))
                                 match = m;
- fclose(fp);
+ if (fshut(fp, argv[i]))
+ match = Error;
                 }
         }
+
+ enfshut(Error, stdin, "<stdin>");
+ enfshut(Error, stdout, "<stdout>");
         return match;
 }
diff --git a/head.c b/head.c
index 5137729..a7f08d2 100644
--- a/head.c
+++ b/head.c
_AT_@ -62,9 +62,10 @@ main(int argc, char *argv[])
                         }
                         newline = 1;
                         head(fp, *argv, n);
- fclose(fp);
+ if(fshut(fp, *argv))
+ ret = 1;
                 }
         }
 
- return ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/hostname.c b/hostname.c
index 2aad4ad..dff32af 100644
--- a/hostname.c
+++ b/hostname.c
_AT_@ -32,5 +32,5 @@ main(int argc, char *argv[])
                 usage();
         }
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/kill.c b/kill.c
index 8a62b54..a3429a0 100644
--- a/kill.c
+++ b/kill.c
_AT_@ -74,17 +74,15 @@ main(int argc, char *argv[])
                         if (!argc) {
                                 for (i = 0; i < LEN(sigs); i++)
                                         puts(sigs[i].name);
- return 0;
                         } else if (argc == 1) {
                                 sig = estrtonum(*argv, 0, INT_MAX);
                                 if (sig > 128)
                                         sig = WTERMSIG(sig);
                                 puts(sig2name(sig));
- return 0;
                         } else {
                                 usage();
                         }
- break;
+ return fshut(stdout, "<stdout>");
                 case 's':
                         if ((*argv)[2])
                                 goto longopt;
diff --git a/libutil/concat.c b/libutil/concat.c
index 551b5b9..fad9471 100644
--- a/libutil/concat.c
+++ b/libutil/concat.c
_AT_@ -12,11 +12,8 @@ concat(FILE *fp1, const char *s1, FILE *fp2, const char *s2)
 
         while ((n = fread(buf, 1, sizeof(buf), fp1))) {
                 fwrite(buf, 1, n, fp2);
- if (ferror(fp2))
- eprintf("fwrite %s:", s2);
- if (feof(fp1) || ferror(fp1))
+
+ if (feof(fp1) || ferror(fp1) || ferror(fp2))
                         break;
         }
- if (ferror(fp1))
- eprintf("fread %s", s1);
 }
diff --git a/libutil/fshut.c b/libutil/fshut.c
new file mode 100644
index 0000000..f243a82
--- /dev/null
+++ b/libutil/fshut.c
_AT_@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../util.h"
+
+int fshut(FILE *fp, const char *fname)
+{
+ int ret = 0;
+
+ if (fflush(fp) && !ret) {
+ weprintf("fflush %s:", fname);
+ ret = 1;
+ }
+
+ if (ferror(fp) && !ret) {
+ weprintf("ferror %s:", fname);
+ ret = 1;
+ }
+
+ if (fclose(fp) && !ret) {
+ weprintf("fclose %s:", fname);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+void enfshut(int status, FILE *fp, const char *fname)
+{
+ if (fshut(fp, fname))
+ exit(status);
+}
+
+void efshut(FILE *fp, const char *fname)
+{
+ enfshut(1, fp, fname);
+}
diff --git a/logger.c b/logger.c
index a4c240e..36e20d1 100644
--- a/logger.c
+++ b/logger.c
_AT_@ -72,8 +72,6 @@ main(int argc, char *argv[])
         if (!argc) {
                 while (getline(&buf, &sz, stdin) > 0)
                         syslog(priority, "%s", buf);
- if (ferror(stdin))
- eprintf("getline %s:", "<stdin>");
         } else {
                 for (i = 0, sz = 0; i < argc; i++)
                         sz += strlen(argv[i]);
_AT_@ -89,5 +87,5 @@ main(int argc, char *argv[])
 
         closelog();
 
- return 0;
+ return fshut(stdin, "<stdin>");
 }
diff --git a/logname.c b/logname.c
index 11d287b..2a591cd 100644
--- a/logname.c
+++ b/logname.c
_AT_@ -25,5 +25,5 @@ main(int argc, char *argv[])
         else
                 eprintf("no login name\n");
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/ls.c b/ls.c
index 6fce25e..91c055d 100644
--- a/ls.c
+++ b/ls.c
_AT_@ -365,5 +365,5 @@ main(int argc, char *argv[])
         for (i = 0; i < argc; i++)
                 ls(&ents[rflag ? argc-i-1 : i], 1);
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/md5sum.c b/md5sum.c
index 5baeecf..7aeb9e1 100644
--- a/md5sum.c
+++ b/md5sum.c
_AT_@ -35,5 +35,6 @@ main(int argc, char *argv[])
                 usage();
         } ARGEND;
 
- return cryptfunc(argc, argv, &md5_ops, md, sizeof(md));
+ return cryptfunc(argc, argv, &md5_ops, md, sizeof(md)) ||
+ !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
 }
diff --git a/mktemp.c b/mktemp.c
index b4ecaf1..e25ef43 100644
--- a/mktemp.c
+++ b/mktemp.c
_AT_@ -61,9 +61,11 @@ main(int argc, char *argv[])
                                 eprintf("mkstemp %s:", path);
                         return 1;
                 }
- close(fd);
+ if (close(fd))
+ eprintf("close %s:", path);
         }
         puts(path);
 
+ efshut(stdout, "<stdout>");
         return 0;
 }
diff --git a/nl.c b/nl.c
index 7609d5e..b84fe32 100644
--- a/nl.c
+++ b/nl.c
_AT_@ -193,8 +193,8 @@ main(int argc, char *argv[])
                 if (!(fp = fopen(argv[0], "r")))
                         eprintf("fopen %s:", argv[0]);
                 nl(argv[0], fp);
- fclose(fp);
         }
 
- return 0;
+ return !!(fshut(fp, argv[0]) + fshut(stdin, "<stdin>") +
+ fshut(stdout, "<stdout>"));
 }
diff --git a/paste.c b/paste.c
index 5ccda3a..dc9c32a 100644
--- a/paste.c
+++ b/paste.c
_AT_@ -86,10 +86,10 @@ int
 main(int argc, char *argv[])
 {
         struct fdescr *dsc;
- Rune *delim;
+ Rune *delim;
         size_t i, len;
- int seq = 0;
- char *adelim = "\t";
+ int seq = 0, ret = 0;
+ char *adelim = "\t";
 
         ARGBEGIN {
         case 's':
_AT_@ -116,22 +116,23 @@ main(int argc, char *argv[])
         dsc = ereallocarray(NULL, argc, sizeof(*dsc));
 
         for (i = 0; i < argc; i++) {
- if (!strcmp(argv[i], "-"))
+ if (!strcmp(argv[i], "-")) {
                         dsc[i].fp = stdin;
- else
- dsc[i].fp = fopen(argv[i], "r");
- if (!dsc[i].fp)
+ } else if (!(dsc[i].fp = fopen(argv[i], "r"))) {
                         eprintf("fopen %s:", argv[i]);
+ }
                 dsc[i].name = argv[i];
         }
 
- if (seq)
+ if (seq) {
                 sequential(dsc, argc, delim, len);
- else
+ } else {
                 parallel(dsc, argc, delim, len);
+ }
 
         for (i = 0; i < argc; i++)
- fclose(dsc[i].fp);
+ if (dsc[i].fp != stdin && fshut(dsc[i].fp, argv[i]))
+ ret = 1;
 
- return 0;
+ return fshut(stdin, "<stdin>") || fshut(stdout, "<stdout>") || ret;
 }
diff --git a/printenv.c b/printenv.c
index 135e0e3..f88e4d2 100644
--- a/printenv.c
+++ b/printenv.c
_AT_@ -35,5 +35,5 @@ main(int argc, char *argv[])
                 }
         }
 
- return ret;
+ return fshut(stdout, "<stdout>") || ret;
 }
diff --git a/printf.c b/printf.c
index 8c204b8..6c99ad2 100644
--- a/printf.c
+++ b/printf.c
_AT_@ -152,5 +152,5 @@ main(int argc, char *argv[])
                         cooldown = 1;
         }
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/pwd.c b/pwd.c
index 759bdcd..a506cea 100644
--- a/pwd.c
+++ b/pwd.c
_AT_@ -46,5 +46,5 @@ main(int argc, char *argv[])
                 eprintf("getcwd:");
         puts((mode == 'L') ? getpwd(cwd) : cwd);
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/readlink.c b/readlink.c
index e80767f..3fa1f2e 100644
--- a/readlink.c
+++ b/readlink.c
_AT_@ -91,5 +91,5 @@ mdone:
         if (!nflag)
                 putchar('\n');
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/sed.c b/sed.c
index 59bf9cb..ddf90f5 100644
--- a/sed.c
+++ b/sed.c
_AT_@ -433,8 +433,7 @@ compile(char *s, int isfile)
                 }
         }
 
- if (fclose(f))
- weprintf("fclose:");
+ fshut(f, s);
 }
 
 /* FIXME: if we decide to honor lack of trailing newline, set/clear a global
_AT_@ -1119,8 +1118,8 @@ next_file(void)
 
         if (file == stdin)
                 clearerr(file);
- else if (file && fclose(file))
- weprintf("fclose:");
+ if (file)
+ fshut(file, "<file>");
         file = NULL;
 
         do {
_AT_@ -1188,8 +1187,7 @@ write_file(char *path, FILE *out)
         while (read_line(in, &genbuf) != EOF)
                 check_puts(genbuf.str, out);
 
- if (fclose(in))
- weprintf("fclose:");
+ fshut(in, path);
 }
 
 static void
_AT_@ -1730,5 +1728,6 @@ main(int argc, char *argv[])
 
         files = argv;
         run();
- return 0;
+
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
 }
diff --git a/seq.c b/seq.c
index 5a306ea..4f2dd48 100644
--- a/seq.c
+++ b/seq.c
_AT_@ -143,5 +143,5 @@ main(int argc, char *argv[])
         }
         putchar('\n');
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/sha1sum.c b/sha1sum.c
index b7222fd..6a564e5 100644
--- a/sha1sum.c
+++ b/sha1sum.c
_AT_@ -34,5 +34,6 @@ main(int argc, char *argv[])
                 usage();
         } ARGEND;
 
- return cryptfunc(argc, argv, &sha1_ops, md, sizeof(md));
+ return cryptfunc(argc, argv, &sha1_ops, md, sizeof(md)) ||
+ !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
 }
diff --git a/sha256sum.c b/sha256sum.c
index 06e8832..3c898c7 100644
--- a/sha256sum.c
+++ b/sha256sum.c
_AT_@ -34,5 +34,6 @@ main(int argc, char *argv[])
                 usage();
         } ARGEND;
 
- return cryptfunc(argc, argv, &sha256_ops, md, sizeof(md));
+ return cryptfunc(argc, argv, &sha256_ops, md, sizeof(md)) ||
+ !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
 }
diff --git a/sha512sum.c b/sha512sum.c
index a0fc3cc..7dd547b 100644
--- a/sha512sum.c
+++ b/sha512sum.c
_AT_@ -34,5 +34,6 @@ main(int argc, char *argv[])
                 usage();
         } ARGEND;
 
- return cryptfunc(argc, argv, &sha512_ops, md, sizeof(md));
+ return cryptfunc(argc, argv, &sha512_ops, md, sizeof(md)) ||
+ !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
 }
diff --git a/sort.c b/sort.c
index 58e0b91..3e4f3a3 100644
--- a/sort.c
+++ b/sort.c
_AT_@ -236,7 +236,7 @@ main(int argc, char *argv[])
         FILE *fp, *ofp = stdout;
         struct linebuf linebuf = EMPTY_LINEBUF;
         size_t i;
- int global_flags = 0;
+ int global_flags = 0, ret = 0;
         char *outfile = NULL;
 
         ARGBEGIN {
_AT_@ -300,7 +300,8 @@ main(int argc, char *argv[])
                 } else {
                         getlines(fp, &linebuf);
                 }
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
         }
 
         if (!Cflag && !cflag) {
_AT_@ -318,5 +319,7 @@ main(int argc, char *argv[])
                 }
         }
 
- return 0;
+ enfshut(2, stdin, "<stdin>");
+ enfshut(2, stdout, "<stdout>");
+ return ret;
 }
diff --git a/split.c b/split.c
index c0aa87e..c4c777d 100644
--- a/split.c
+++ b/split.c
_AT_@ -27,7 +27,7 @@ nextfile(FILE *f, char *buf, int plen, int slen)
         static int filecount = 0;
 
         if (f)
- fclose(f);
+ fshut(f, "<file>");
         if (itostr(buf + plen, filecount++, slen) < 0)
                 return NULL;
 
_AT_@ -124,9 +124,6 @@ main(int argc, char *argv[])
                 putc(ch, out);
         }
 
- fclose(in);
- if (out)
- fclose(out);
-
- return 0;
+ return !!(fshut(in, "<infile>") + (out && fshut(out, "<outfile>")) +
+ fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
 }
diff --git a/sponge.c b/sponge.c
index bcc0f7a..ee1d338 100644
--- a/sponge.c
+++ b/sponge.c
_AT_@ -32,8 +32,5 @@ main(int argc, char *argv[])
                 eprintf("fopen %s:", argv[0]);
         concat(tmpfp, "<tmpfile>", fp, argv[0]);
 
- fclose(fp);
- fclose(tmpfp);
-
- return 0;
+ return !!(fshut(fp, argv[0]) + fshut(tmpfp, "<tmpfile>"));
 }
diff --git a/strings.c b/strings.c
index 8c6c094..598b2e4 100644
--- a/strings.c
+++ b/strings.c
_AT_@ -85,9 +85,10 @@ main(int argc, char *argv[])
                                 continue;
                         }
                         strings(fp, *argv, len);
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
                 }
         }
 
- return ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/tail.c b/tail.c
index 888dd47..65d6c97 100644
--- a/tail.c
+++ b/tail.c
_AT_@ -130,7 +130,8 @@ main(int argc, char *argv[])
                         tail(fp, *argv);
 
                         if (!fflag) {
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
                                 continue;
                         }
                         for (tmp = NULL, tmpsize = 0;;) {
_AT_@ -155,5 +156,5 @@ main(int argc, char *argv[])
                 }
         }
 
- return ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/tar.c b/tar.c
index 31cc399..d0d72a1 100644
--- a/tar.c
+++ b/tar.c
_AT_@ -166,8 +166,7 @@ archive(const char *path)
                         if (fwrite(b, BLKSIZ, 1, tarfile) != 1)
                                 eprintf("fwrite:");
                 }
- if (fclose(f) == EOF)
- eprintf("fclose %s:", path);
+ efshut(f, path);
         }
 
         return 0;
_AT_@ -246,8 +245,8 @@ unarchive(char *fname, ssize_t l, char b[BLKSIZ])
                 if (f && fwrite(b, MIN(l, BLKSIZ), 1, f) != 1)
                         eprintf("fwrite %s:", fname);
         }
- if (f && fclose(f) == EOF)
- eprintf("fclose %s:", fname);
+ if (f)
+ fshut(f, fname);
 
         if (!mflag) {
                 times[0].tv_sec = times[1].tv_sec = mtime;
diff --git a/tee.c b/tee.c
index 3bf1946..c0ad6f2 100644
--- a/tee.c
+++ b/tee.c
_AT_@ -46,8 +46,6 @@ main(int argc, char *argv[])
                         eprintf("fwrite %s:", (i != argc) ? argv[i] : "<stdout>");
                 }
         }
- if (ferror(stdin))
- eprintf("fread <stdin>:");
 
- return 0;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
 }
diff --git a/tr.c b/tr.c
index 5dcc307..83d7b69 100644
--- a/tr.c
+++ b/tr.c
_AT_@ -204,7 +204,7 @@ main(int argc, char *argv[])
                 eprintf("set2 can't be imaged to from a complement.\n");
 read:
         if (!efgetrune(&r, stdin, "<stdin>"))
- return 0;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>"));
         off1 = off2 = 0;
         for (i = 0; i < set1ranges; i++) {
                 if (set1[i].start <= r && r <= set1[i].end) {
diff --git a/tty.c b/tty.c
index 1c23bf4..6b580d3 100644
--- a/tty.c
+++ b/tty.c
_AT_@ -26,5 +26,5 @@ main(int argc, char *argv[])
         tty = ttyname(STDIN_FILENO);
         puts(tty ? tty : "not a tty");
 
- return !tty;
+ return fshut(stdout, "<stdout>") || !tty;
 }
diff --git a/uname.c b/uname.c
index f0e9264..2fa3960 100644
--- a/uname.c
+++ b/uname.c
_AT_@ -55,5 +55,5 @@ main(int argc, char *argv[])
                 putword(u.machine);
         putchar('\n');
 
- return 0;
+ return fshut(stdout, "<stdout>");
 }
diff --git a/unexpand.c b/unexpand.c
index 17dd532..333b8e9 100644
--- a/unexpand.c
+++ b/unexpand.c
_AT_@ -159,7 +159,8 @@ main(int argc, char *argv[])
                                 continue;
                         }
                         unexpand(*argv, fp);
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
                 }
         }
 
diff --git a/uniq.c b/uniq.c
index cb96c13..030b622 100644
--- a/uniq.c
+++ b/uniq.c
_AT_@ -131,10 +131,9 @@ main(int argc, char *argv[])
                                 eprintf("fopen %s:", argv[1]);
                 }
                 uniq(fp, ofp);
- fclose(fp);
         }
         uniqfinish(ofp);
- fclose(ofp);
 
- return 0;
+ return !!(fshut(fp, fp == stdin ? "<stdin>" : argv[0]) +
+ fshut(ofp, ofp == stdout ? "<stdout>" : argv[1]));
 }
diff --git a/util.h b/util.h
index d4415a5..a878d73 100644
--- a/util.h
+++ b/util.h
_AT_@ -3,6 +3,7 @@
 
 #include <regex.h>
 #include <stddef.h>
+#include <stdio.h>
 
 #include "arg.h"
 #include "compat.h"
_AT_@ -34,6 +35,10 @@ void *enrealloc(int, void *, size_t);
 char *enstrdup(int, const char *);
 char *enstrndup(int, const char *, size_t);
 
+void enfshut(int, FILE *, const char *);
+void efshut(FILE *, const char *);
+int fshut(FILE *, const char *);
+
 void enprintf(int, const char *, ...);
 void eprintf(const char *, ...);
 void weprintf(const char *, ...);
diff --git a/uudecode.c b/uudecode.c
index 7c18af6..a443e7c 100644
--- a/uudecode.c
+++ b/uudecode.c
_AT_@ -273,10 +273,7 @@ main(int argc, char *argv[])
 
         if (nfp != stdout && chmod(fname, mode) < 0)
                 eprintf("chmod %s:", fname);
- if (fp)
- fclose(fp);
- if (nfp)
- fclose(nfp);
 
- return 0;
+ return !!(fshut(fp, fp == stdin ? "<stdin>" : argv[0]) +
+ fshut(nfp, nfp == stdout ? "<stdout>" : fname));
 }
diff --git a/uuencode.c b/uuencode.c
index 63ea7bd..ddd68ad 100644
--- a/uuencode.c
+++ b/uuencode.c
_AT_@ -101,7 +101,7 @@ usage(void)
 int
 main(int argc, char *argv[])
 {
- FILE *fp;
+ FILE *fp = NULL;
 
         ARGBEGIN {
         case 'm':
_AT_@ -126,8 +126,8 @@ main(int argc, char *argv[])
                         uuencodeb64(fp, argv[1], argv[0]);
                 else
                         uuencode(fp, argv[1], argv[0]);
- fclose(fp);
         }
 
- return 0;
+ return !!((fp && fshut(fp, argv[0])) + fshut(stdin, "<stdin>") +
+ fshut(stdout, "<stdout>"));
 }
diff --git a/wc.c b/wc.c
index 0b196d8..ed2c94d 100644
--- a/wc.c
+++ b/wc.c
_AT_@ -91,11 +91,12 @@ main(int argc, char *argv[])
                                 continue;
                         }
                         wc(fp, *argv);
- fclose(fp);
+ if (fshut(fp, *argv))
+ ret = 1;
                 }
                 if (many)
                         output("total", tc, tl, tw);
         }
 
- return ret;
+ return !!(fshut(stdin, "<stdin>") + fshut(stdout, "<stdout>")) || ret;
 }
diff --git a/xargs.c b/xargs.c
index de09ae9..92e0745 100644
--- a/xargs.c
+++ b/xargs.c
_AT_@ -269,5 +269,6 @@ main(int argc, char *argv[])
 
         free(argb);
 
- return nerrors ? 123 : 0;
+ return (nerrors || !!(fshut(stdin, "<stdin>") +
+ fshut(stdout, "<stdout>"))) ? 123 : 0;
 }
Received on Sun Apr 05 2015 - 10:14:04 CEST

This archive was generated by hypermail 2.3.0 : Sun Apr 05 2015 - 10:24:12 CEST