/* closeout.c - close standard output
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software
- Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free
+ Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "closeout.h"
#include <stdio.h>
+#include <stdbool.h>
#include <errno.h>
#include "gettext.h"
#include "error.h"
#include "exitfail.h"
#include "quotearg.h"
+#include "__fpending.h"
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
void
close_stdout (void)
{
- int e = ferror (stdout) ? 0 : -1;
+ bool none_pending = (__fpending (stdout) == 0);
+ bool prev_fail = (ferror (stdout) != 0);
+ bool fclose_fail = (fclose (stdout) != 0);
- if (fclose (stdout) != 0)
- e = errno;
-
- if (0 <= e)
+ if (prev_fail || fclose_fail)
{
- char const *write_error = _("write error");
+ int e = fclose_fail ? errno : 0;
+ char const *write_error;
+
+ /* If ferror returned zero, no data remains to be flushed, and we'd
+ otherwise fail with EBADF due to a failed fclose, then assume that
+ it's ok to ignore the fclose failure. That can happen when a
+ program like cp is invoked like this `cp a b >&-' (i.e., with
+ stdout closed) and doesn't generate any output (hence no previous
+ error and nothing to be flushed). */
+ if (e == EBADF && !prev_fail && none_pending)
+ return;
+
+ write_error = _("write error");
if (file_name)
error (exit_failure, e, "%s: %s", quotearg_colon (file_name),
write_error);