bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

adding bulletproofing for cases where stdin, stdout, stderr are closed


From: Paul Eggert
Subject: adding bulletproofing for cases where stdin, stdout, stderr are closed
Date: Mon, 11 Apr 2005 13:31:41 -0700

I installed the following patch to add bulletproofing for the cases
where stdin, stdout, or stderr are closed, and where open and/or
fopen can return one of the standard descriptors unexpectedly.

Unfortunately it's tricky to come up with test cases to illustrate the
problems here, since they often rely on a weird scenario like an I/O
error causing a diagnostic to be put into a file unexpectedly.

I can't promise that I caught all the troublesome scenarios, but I
patched all the ones I found.

2005-04-11  Paul Eggert  <address@hidden>

        Add bulletproofing for cases where stdin, stdout, or stderr are closed.
        * lib/fcntl-safer.h, lib/open-safer.c: Remove.
        * lib/fd-safer.c: New file.
        * lib/dup-safer.c: Include unistd-safer.h first, to test interface.
        (dup_safer) [!deefined F_DUPD]: Use new fd_safer function instead of
        rolling our own code.
        * lib/fts.c: Include unistd-safer.h.
        (fts_safe_changedir): Use fd_safer.
        * lib/getloadavg.c: Include unistd-safer.h.
        (getloadavg): Use fd_safer.
        * lib/getusershell.c: Include stdio-safer.h.
        (getusershell): Use fopen_safer.
        * lib/save-cwd.c: Include unistd-safer.h.
        (save_cwd): Use fd_safer.
        * lib/unistd-safer.h (fd_safer): New decl.
        * lib/Makefile.am (libfetish_a_SOURCES): Remove dup-safer.c,
        fcntl-safer.h, fopen-safer.c, open-safer.c, stdio-safer.h,
        unistd-safer.h.
        * m4/fcntl-safer.m4: Remove.
        * m4/stdio-safer.m4 (gl_STDIO_SAFER): Use AC_LIBSOURCES and AC_LIBOBJ.
        * m4/unistd-safer.m4 (gl_UNISTD_SAFER): Likewise.
        Invoke gl_PREREQ_FD_SAFER.
        (gl_PREREQ_FD_SAFER): New macro.
        * m4/prereq.m4 (gl_PREREQ): Don't require gl_FCNTL_SAFER.
        * src/comm.c: Include stdio-safer.h.
        (compare_files): Exit right away on I/O error rather than continuing
        and producing confusing output and error messages.
        Return void, not int; all callers changed.
        Use fopen_safer to avoid confusion with file descriptors.
        * src/copy.c: Include unistd-safer.h.
        (copy_reg): Use fd_safer.
        * src/csplit.c: Include stdio-safer.h.
        (input_desc): Remove unnecessary static initialization.
        (set_input_file): Use STDIN_FILENO, not 0.
        (create_output_file): Use fopen_safer.
        * src/dircolors.c (dc_parse_file): Don't assume fopen does not
        return stdin.
        * src/head.c (head_file): Don't assume open does not return 0.
        * src/join.c: Include stdio-safer.h.
        (main): Use fopen_safer.  Simplify the resulting code.
        * src/md5sum.c (digest_file, digest_check):
        Don't assume that fopen does not return stdin.
        * src/nohup.c: Include unistd-safer.h.
        (main): Don't dup stderr to stdin or stdout by mistake.
        * src/od.c (check_and_close): Don't assume fopen does not return stdin.
        * src/paste.c (paste_serial): Likewise.
        * src/pr.c: Include stdio-safer.h.
        (open_file): Use fopen_safer.
        (close_file): Don't assume fopen does not return stdin.
        * src/ptx.c (main): Don't assume fopen returns stdout after closing
        stdout.  Use freopen instead.
        * src/shred.c: Include unistd-safer.h.
        (wipename): Use fd_safer on directory file descriptor.
        (wipefile): Remove special case for /dev/fd/* on older hosts.
        It didn't work in general, and wasn't documented.
        Use fd_safer.
        * src/sort.c: Include unistd-safer.h.
        (create_temp_file): Use fd_safer.
        (xfclose): Don't assume fileno (stdin) == STDIN_FILENO, etc.
        * src/split.c: Include unistd-safer.h.
        (cwrite): Use fd_safer.  Replace mystery constant 0666 with symbolic
        version, as POSIX requires.
        * src/sum.c (bsd_sum_file, sysv_sym_file):
        Use same pattern as elsewhere for checking for stdin.
        * src/tac.c: Include unistd-safer.h.
        (copy_to_temp): Use fd_safer.
        (tac_file): Don't assume fopen cannot return stdin.
        * src/tail.c: Include unistd-safer.h rather than fcntl-safer.h.
        (recheck, tail_file): Use fd_safer rather than open_safer.
        * src/tee.c: Include stdio-safer.h.
        (tee): Use fopen_safer.
        * src/touch.c: Include unistd-safer.h.
        (touch): Use fd_safer.
        * src/tsort.c (have_read_stdin): Remove; no longer needed.  All uses
        removed.
        (tsort): Do not assume fopen can't return stdin.
        Close stdin before returning.  All uses changed.
        * src/unexpand.c (next_file): Don't assume fopen cannot return stdin.
        * src/uniq.c: Include stdio_safer.h.
        (check_file): Don't assume fopen cannot return stdin or stdout.

Remove lib/fcntl-safer.h, lib/open-safer.c, and m4/fcntl-safer.m4 in
addition to this patch.

--- /dev/null   2003-03-18 13:55:57 -0800
+++ lib/fd-safer.c      2005-04-11 11:24:45 -0700
@@ -0,0 +1,61 @@
+/* Return a safer copy of a file descriptor.
+
+   Copyright (C) 2005 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
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   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.  */
+
+/* Written by Paul Eggert.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "unistd-safer.h"
+
+#include <errno.h>
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Return FD, unless FD would be a copy of standard input, output, or
+   error; in that case, return a duplicate of FD, closing FD.  On
+   failure to duplicate, close FD, set errno, and return -1.  Preserve
+   errno if FD is negative, so that the caller can always inspect
+   errno when the returned value is negative.
+
+   This function is usefully wrapped around functions that return file
+   descriptors, e.g., fd_safer (open ("file", O_RDONLY)).  */
+
+int
+fd_safer (int fd)
+{
+  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
+    {
+      int f = dup_safer (fd);
+      int e = errno;
+      close (fd);
+      errno = e;
+      fd = f;
+    }
+
+  return fd;
+}
Index: lib/dup-safer.c
===================================================================
RCS file: /fetish/cu/lib/dup-safer.c,v
retrieving revision 1.3
diff -p -u -r1.3 dup-safer.c
--- lib/dup-safer.c     2 Aug 2004 22:47:00 -0000       1.3
+++ lib/dup-safer.c     11 Apr 2005 19:38:49 -0000
@@ -1,5 +1,5 @@
 /* Invoke dup, but avoid some glitches.
-   Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2004, 2005 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
@@ -21,7 +21,7 @@
 # include <config.h>
 #endif
 
-#include <errno.h>
+#include "unistd-safer.h"
 
 #if HAVE_FCNTL_H
 # include <fcntl.h>
@@ -34,8 +34,6 @@
 # define STDERR_FILENO 2
 #endif
 
-#include <unistd-safer.h>
-
 /* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
    STDERR_FILENO.  */
 
@@ -45,15 +43,8 @@ dup_safer (int fd)
 #ifdef F_DUPFD
   return fcntl (fd, F_DUPFD, STDERR_FILENO + 1);
 #else
-  int f = dup (fd);
-  if (0 <= f && f <= STDERR_FILENO)
-    {
-      int f1 = dup_safer (f);
-      int e = errno;
-      close (f);
-      errno = e;
-      f = f1;
-    }
-  return f;
+  /* fd_safer calls us back, but eventually the recursion unwinds and
+     does the right thing.  */
+  return fd_safer (dup (fd));
 #endif
 }
Index: lib/fts.c
===================================================================
RCS file: /fetish/cu/lib/fts.c,v
retrieving revision 1.23
diff -p -u -r1.23 fts.c
--- lib/fts.c   9 Apr 2005 14:19:49 -0000       1.23
+++ lib/fts.c   11 Apr 2005 19:38:49 -0000
@@ -68,6 +68,7 @@ static char sccsid[] = "@(#)fts.c     8.6 (B
 #include "dirfd.h"
 #include "fts_.h"
 #include "intprops.h"
+#include "unistd-safer.h"
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -1429,7 +1430,7 @@ fts_safe_changedir(sp, p, fd, path)
        newfd = fd;
        if (ISSET(FTS_NOCHDIR))
                return (0);
-       if (fd < 0 && (newfd = diropen (path)) < 0)
+       if (fd < 0 && (newfd = fd_safer (diropen (path))) < 0)
                return (-1);
        if (fstat(newfd, &sb)) {
                ret = -1;
Index: lib/getloadavg.c
===================================================================
RCS file: /fetish/cu/lib/getloadavg.c,v
retrieving revision 1.27
diff -p -u -r1.27 getloadavg.c
--- lib/getloadavg.c    9 Mar 2005 19:21:43 -0000       1.27
+++ lib/getloadavg.c    11 Apr 2005 19:38:50 -0000
@@ -452,6 +452,8 @@
 # else
 #  include <sys/file.h>
 # endif
+
+# include "unistd-safer.h"
 
 /* Avoid static vars inside a function since in HPUX they dump as pure.  */
 
@@ -911,7 +913,7 @@ getloadavg (double loadavg[], int nelem)
   if (!getloadavg_initialized)
     {
 #  ifndef SUNOS_5
-      channel = open ("/dev/kmem", 0);
+      channel = fd_safer (open ("/dev/kmem", O_RDONLY));
       if (channel >= 0)
        {
          /* Set the channel to close on exec, so it does not
Index: lib/getusershell.c
===================================================================
RCS file: /fetish/cu/lib/getusershell.c,v
retrieving revision 1.18
diff -p -u -r1.18 getusershell.c
--- lib/getusershell.c  4 Oct 2004 20:18:43 -0000       1.18
+++ lib/getusershell.c  11 Apr 2005 19:38:50 -0000
@@ -1,6 +1,6 @@
 /* getusershell.c -- Return names of valid user shells.
 
-   Copyright (C) 1991, 1997, 2000, 2001, 2003, 2004 Free Software
+   Copyright (C) 1991, 1997, 2000, 2001, 2003, 2004, 2005 Free Software
    Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 #include <ctype.h>
 
+#include "stdio-safer.h"
 #include "xalloc.h"
 
 #if USE_UNLOCKED_IO
@@ -98,7 +99,7 @@ getusershell (void)
 
   if (shellstream == NULL)
     {
-      shellstream = fopen (SHELLS_FILE, "r");
+      shellstream = fopen_safer (SHELLS_FILE, "r");
       if (shellstream == NULL)
        {
          /* No shells file.  Use the default list.  */
Index: lib/save-cwd.c
===================================================================
RCS file: /fetish/cu/lib/save-cwd.c,v
retrieving revision 1.25
diff -p -u -r1.25 save-cwd.c
--- lib/save-cwd.c      9 Mar 2005 23:21:00 -0000       1.25
+++ lib/save-cwd.c      11 Apr 2005 19:38:50 -0000
@@ -42,6 +42,7 @@
 #include <errno.h>
 
 #include "chdir-long.h"
+#include "unistd-safer.h"
 #include "xgetcwd.h"
 
 /* On systems without the fchdir function (WOE), pretend that open
@@ -49,7 +50,7 @@
    Since chdir_long requires fchdir, use chdir instead.  */
 #if !HAVE_FCHDIR
 # undef open
-# define open(File, Flags) -1
+# define open(File, Flags) (-1)
 # undef fchdir
 # define fchdir(Fd) (abort (), -1)
 # undef chdir_long
@@ -81,10 +82,10 @@ save_cwd (struct saved_cwd *cwd)
 {
   cwd->name = NULL;
 
-  cwd->desc = open (".", O_RDONLY);
+  cwd->desc = fd_safer (open (".", O_RDONLY));
   if (cwd->desc < 0)
     {
-      cwd->desc = open (".", O_WRONLY);
+      cwd->desc = fd_safer (open (".", O_WRONLY));
       if (cwd->desc < 0)
        {
          cwd->name = xgetcwd ();
Index: lib/unistd-safer.h
===================================================================
RCS file: /fetish/cu/lib/unistd-safer.h,v
retrieving revision 1.3
diff -p -u -r1.3 unistd-safer.h
--- lib/unistd-safer.h  18 Aug 2003 09:44:49 -0000      1.3
+++ lib/unistd-safer.h  11 Apr 2005 19:38:50 -0000
@@ -1,6 +1,6 @@
-/* Invoke unistd functions, but avoid some glitches.
+/* Invoke unistd-like functions, but avoid some glitches.
 
-   Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003, 2005 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
@@ -19,3 +19,4 @@
 /* Written by Paul Eggert.  */
 
 int dup_safer (int);
+int fd_safer (int);
Index: lib/Makefile.am
===================================================================
RCS file: /fetish/cu/lib/Makefile.am,v
retrieving revision 1.217
diff -p -u -r1.217 Makefile.am
--- lib/Makefile.am     21 Mar 2005 22:31:05 -0000      1.217
+++ lib/Makefile.am     11 Apr 2005 19:38:50 -0000
@@ -29,24 +29,18 @@ libfetish_a_SOURCES = \
   allocsa.c allocsa.h \
   dev-ino.h \
   diacrit.c diacrit.h \
-  dup-safer.c \
   euidaccess.h \
   exit.h \
-  fcntl-safer.h \
-  fopen-safer.c \
   full-read.c full-read.h \
   full-write.c full-write.h \
   gettext.h \
   localcharset.c localcharset.h \
   mbswidth.c mbswidth.h \
-  open-safer.c \
   readtokens0.c readtokens0.h \
   regex.h \
   root-dev-ino.c root-dev-ino.h \
-  stdio-safer.h \
   time_r.c time_r.h \
   unicodeio.c unicodeio.h \
-  unistd-safer.h \
   version-etc.c version-etc.h version-etc-fsf.c \
   xalloc-die.c \
   xfts.c xfts.h \
Index: m4/stdio-safer.m4
===================================================================
RCS file: /fetish/cu/m4/stdio-safer.m4,v
retrieving revision 1.2
diff -p -u -r1.2 stdio-safer.m4
--- m4/stdio-safer.m4   23 Jan 2005 09:07:57 -0000      1.2
+++ m4/stdio-safer.m4   11 Apr 2005 19:38:50 -0000
@@ -1,11 +1,14 @@
-# stdio-safer.m4 serial 2
-dnl Copyright (C) 2002 Free Software Foundation, Inc.
+# stdio-safer.m4 serial 3
+dnl Copyright (C) 2002, 2005 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
 AC_DEFUN([gl_STDIO_SAFER],
 [
+  AC_LIBSOURCES([fopen-safer.c, stdio-safer.h])
+  AC_LIBOBJ([fopen-safer])
+
   dnl Prerequisites of lib/fopen-safer.c.
   AC_CHECK_HEADERS_ONCE(unistd.h)
 ])
Index: m4/unistd-safer.m4
===================================================================
RCS file: /fetish/cu/m4/unistd-safer.m4,v
retrieving revision 1.2
diff -p -u -r1.2 unistd-safer.m4
--- m4/unistd-safer.m4  23 Jan 2005 09:07:57 -0000      1.2
+++ m4/unistd-safer.m4  11 Apr 2005 19:38:50 -0000
@@ -1,15 +1,25 @@
-# unistd-safer.m4 serial 2
-dnl Copyright (C) 2002 Free Software Foundation, Inc.
+# unistd-safer.m4 serial 3
+dnl Copyright (C) 2002, 2005 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
 AC_DEFUN([gl_UNISTD_SAFER],
 [
+  AC_LIBSOURCES([dup-safer.c, fd-safer.c, unistd-safer.h])
+  AC_LIBOBJ([dup-safer])
+  AC_LIBOBJ([fd-safer])
+
   gl_PREREQ_DUP_SAFER
+  gl_PREREQ_FD_SAFER
 ])
 
 # Prerequisites of lib/dup-safer.c.
 AC_DEFUN([gl_PREREQ_DUP_SAFER], [
   AC_CHECK_HEADERS_ONCE(fcntl.h unistd.h)
 ])
+
+# Prerequisites of lib/fd-safer.c.
+AC_DEFUN([gl_PREREQ_FD_SAFER], [
+  AC_CHECK_HEADERS_ONCE(unistd.h)
+])
Index: m4/prereq.m4
===================================================================
RCS file: /fetish/cu/m4/prereq.m4,v
retrieving revision 1.106
diff -p -u -r1.106 prereq.m4
--- m4/prereq.m4        21 Mar 2005 20:15:18 -0000      1.106
+++ m4/prereq.m4        11 Apr 2005 19:38:50 -0000
@@ -1,4 +1,4 @@
-#serial 51
+#serial 52
 
 dnl We use gl_ for non Autoconf macros.
 m4_pattern_forbid([^gl_[ABCDEFGHIJKLMNOPQRSTUVXYZ]])dnl
@@ -26,7 +26,6 @@ AC_DEFUN([gl_PREREQ],
   AC_REQUIRE([gl_ERROR])
   AC_REQUIRE([gl_EXCLUDE])
   AC_REQUIRE([gl_EXITFAIL])
-  AC_REQUIRE([gl_FCNTL_SAFER])
   AC_REQUIRE([gl_FILEBLOCKS])
   AC_REQUIRE([gl_FILEMODE])
   AC_REQUIRE([gl_FILE_TYPE])
Index: src/comm.c
===================================================================
RCS file: /fetish/cu/src/comm.c,v
retrieving revision 1.79
diff -p -u -r1.79 comm.c
--- src/comm.c  28 Mar 2005 17:54:13 -0000      1.79
+++ src/comm.c  11 Apr 2005 19:38:50 -0000
@@ -27,6 +27,7 @@
 #include "error.h"
 #include "hard-locale.h"
 #include "quote.h"
+#include "stdio-safer.h"
 #include "xmemcoll.h"
 
 /* The official name of this program (e.g., no `g' prefix).  */
@@ -137,10 +138,9 @@ writeline (const struct linebuffer *line
 /* Compare INFILES[0] and INFILES[1].
    If either is "-", use the standard input for that file.
    Assume that each input file is sorted;
-   merge them and output the result.
-   Return true if successful.  */
+   merge them and output the result.  */
 
-static bool
+static void
 compare_files (char **infiles)
 {
   /* For each file, we have one linebuffer in lb1.  */
@@ -153,9 +153,6 @@ compare_files (char **infiles)
   /* streams[i] holds the input stream for file i.  */
   FILE *streams[2];
 
-  /* errno values for each stream.  */
-  int saved_errno[2];
-
   int i;
   bool ret = true;
 
@@ -164,15 +161,15 @@ compare_files (char **infiles)
     {
       initbuffer (&lb1[i]);
       thisline[i] = &lb1[i];
-      streams[i] = (STREQ (infiles[i], "-") ? stdin : fopen (infiles[i], "r"));
+      streams[i] = (STREQ (infiles[i], "-")
+                   ? stdin
+                   : fopen_safer (infiles[i], "r"));
       if (!streams[i])
-       {
-         error (0, errno, "%s", infiles[i]);
-         return false;
-       }
+       error (EXIT_FAILURE, errno, "%s", infiles[i]);
 
       thisline[i] = readlinebuffer (thisline[i], streams[i]);
-      saved_errno[i] = errno;
+      if (ferror (streams[i]))
+       error (EXIT_FAILURE, errno, "%s", infiles[i]);
     }
 
   while (thisline[0] || thisline[1])
@@ -214,31 +211,20 @@ compare_files (char **infiles)
       if (order >= 0)
        {
          thisline[1] = readlinebuffer (thisline[1], streams[1]);
-         saved_errno[1] = errno;
+         if (ferror (streams[1]))
+           error (EXIT_FAILURE, errno, "%s", infiles[1]);
        }
       if (order <= 0)
        {
          thisline[0] = readlinebuffer (thisline[0], streams[0]);
-         saved_errno[0] = errno;
+         if (ferror (streams[0]))
+           error (EXIT_FAILURE, errno, "%s", infiles[0]);
        }
     }
 
-  /* Free all storage and close all input streams. */
   for (i = 0; i < 2; i++)
-    {
-      free (lb1[i].buffer);
-      if (ferror (streams[i]))
-       {
-         error (0, saved_errno[i], "%s", infiles[i]);
-         ret = false;
-       }
-      if (fclose (streams[i]) != 0)
-       {
-         error (0, errno, "%s", infiles[i]);
-         ret = false;
-       }
-    }
-  return ret;
+    if (fclose (streams[i]) != 0)
+      error (EXIT_FAILURE, errno, "%s", infiles[i]);
 }
 
 int
@@ -297,6 +283,7 @@ main (int argc, char **argv)
       usage (EXIT_FAILURE);
     }
 
-  exit (compare_files (argv + optind)
-       ? EXIT_SUCCESS : EXIT_FAILURE);
+  compare_files (argv + optind);
+
+  exit (EXIT_SUCCESS);
 }
Index: src/copy.c
===================================================================
RCS file: /fetish/cu/src/copy.c,v
retrieving revision 1.178
diff -p -u -r1.178 copy.c
--- src/copy.c  28 Mar 2005 17:55:43 -0000      1.178
+++ src/copy.c  11 Apr 2005 19:38:50 -0000
@@ -41,6 +41,7 @@
 #include "quote.h"
 #include "same.h"
 #include "savedir.h"
+#include "unistd-safer.h"
 #include "utimecmp.h"
 #include "utimens.h"
 #include "xreadlink.h"
@@ -216,6 +217,7 @@ copy_reg (const char *src_path, const ch
   bool make_holes = false;
 
   source_desc = open (src_path, O_RDONLY);
+  source_desc = fd_safer (source_desc);
   if (source_desc < 0)
     {
       error (0, errno, _("cannot open %s for reading"), quote (src_path));
@@ -267,6 +269,7 @@ copy_reg (const char *src_path, const ch
        }
     }
 
+  dest_desc = fd_safer (dest_desc);
   if (dest_desc < 0)
     {
       error (0, errno, _("cannot create regular file %s"), quote (dst_path));
Index: src/csplit.c
===================================================================
RCS file: /fetish/cu/src/csplit.c,v
retrieving revision 1.136
diff -p -u -r1.136 csplit.c
--- src/csplit.c        9 Apr 2005 04:55:05 -0000       1.136
+++ src/csplit.c        11 Apr 2005 19:38:51 -0000
@@ -31,8 +31,9 @@
 
 #include "error.h"
 #include "inttostr.h"
-#include "safe-read.h"
 #include "quote.h"
+#include "safe-read.h"
+#include "stdio-safer.h"
 #include "xstrtol.h"
 
 /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
@@ -130,7 +131,7 @@ void usage (int status);
 char *program_name;
 
 /* Input file descriptor. */
-static int input_desc = 0;
+static int input_desc;
 
 /* Start of buffer list. */
 static struct buffer_record *head = NULL;
@@ -643,7 +644,7 @@ static void
 set_input_file (const char *name)
 {
   if (STREQ (name, "-"))
-    input_desc = 0;
+    input_desc = STDIN_FILENO;
   else
     {
       input_desc = open (name, O_RDONLY);
@@ -939,7 +940,7 @@ create_output_file (void)
 
   /* Create the output file in a critical section, to avoid races.  */
   sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
-  output_stream = fopen (output_filename, "w");
+  output_stream = fopen_safer (output_filename, "w");
   fopen_ok = (output_stream != NULL);
   fopen_errno = errno;
   files_created += fopen_ok;
Index: src/dircolors.c
===================================================================
RCS file: /fetish/cu/src/dircolors.c,v
retrieving revision 1.84
diff -p -u -r1.84 dircolors.c
--- src/dircolors.c     26 Mar 2005 17:39:17 -0000      1.84
+++ src/dircolors.c     11 Apr 2005 19:38:51 -0000
@@ -376,8 +376,9 @@ dc_parse_file (const char *filename)
 {
   FILE *fp;
   bool ok;
+  bool is_stdin = STREQ (filename, "-");
 
-  if (STREQ (filename, "-"))
+  if (is_stdin)
     {
       have_read_stdin = true;
       fp = stdin;
@@ -398,7 +399,7 @@ dc_parse_file (const char *filename)
 
   ok = dc_parse_stream (fp, filename);
 
-  if (fp != stdin && fclose (fp) == EOF)
+  if (!is_stdin && fclose (fp) != 0)
     {
       error (0, errno, "%s", quote (filename));
       return false;
Index: src/head.c
===================================================================
RCS file: /fetish/cu/src/head.c,v
retrieving revision 1.97
diff -p -u -r1.97 head.c
--- src/head.c  30 Jan 2005 17:57:24 -0000      1.97
+++ src/head.c  11 Apr 2005 19:38:51 -0000
@@ -851,8 +851,9 @@ head_file (const char *filename, uintmax
 {
   int fd;
   bool ok;
+  bool is_stdin = STREQ (filename, "-");
 
-  if (STREQ (filename, "-"))
+  if (is_stdin)
     {
       have_read_stdin = true;
       fd = STDIN_FILENO;
@@ -869,7 +870,7 @@ head_file (const char *filename, uintmax
     }
 
   ok = head (filename, fd, n_units, count_lines, elide_from_end);
-  if (fd != STDIN_FILENO && close (fd) == -1)
+  if (!is_stdin && close (fd) != 0)
     {
       error (0, errno, _("closing %s"), quote (filename));
       return false;
Index: src/join.c
===================================================================
RCS file: /fetish/cu/src/join.c,v
retrieving revision 1.134
diff -p -u -r1.134 join.c
--- src/join.c  8 Dec 2004 23:05:13 -0000       1.134
+++ src/join.c  11 Apr 2005 19:38:51 -0000
@@ -1,5 +1,5 @@
 /* join - join lines of two files on a common field
-   Copyright (C) 91, 1995-2004 Free Software Foundation, Inc.
+   Copyright (C) 91, 1995-2005 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
@@ -31,6 +31,7 @@
 #include "memcasecmp.h"
 #include "posixver.h"
 #include "quote.h"
+#include "stdio-safer.h"
 #include "xmemcoll.h"
 #include "xstrtol.h"
 
@@ -852,22 +853,20 @@ main (int argc, char **argv)
       usage (EXIT_FAILURE);
     }
 
-  fp1 = STREQ (names[0], "-") ? stdin : fopen (names[0], "r");
+  fp1 = STREQ (names[0], "-") ? stdin : fopen_safer (names[0], "r");
   if (!fp1)
     error (EXIT_FAILURE, errno, "%s", names[0]);
-  fp2 = STREQ (names[1], "-") ? stdin : fopen (names[1], "r");
+  fp2 = STREQ (names[1], "-") ? stdin : fopen_safer (names[1], "r");
   if (!fp2)
     error (EXIT_FAILURE, errno, "%s", names[1]);
   if (fp1 == fp2)
     error (EXIT_FAILURE, errno, _("both files cannot be standard input"));
   join (fp1, fp2);
 
-  if (fp1 != stdin && fclose (fp1) == EOF)
+  if (fclose (fp1) != 0)
     error (EXIT_FAILURE, errno, "%s", names[0]);
-  if (fp2 != stdin && fclose (fp2) == EOF)
+  if (fclose (fp2) != 0)
     error (EXIT_FAILURE, errno, "%s", names[1]);
-  if ((fp1 == stdin || fp2 == stdin) && fclose (stdin) == EOF)
-    error (EXIT_FAILURE, errno, "-");
 
   exit (EXIT_SUCCESS);
 }
Index: src/md5sum.c
===================================================================
RCS file: /fetish/cu/src/md5sum.c,v
retrieving revision 1.130
diff -p -u -r1.130 md5sum.c
--- src/md5sum.c        7 Apr 2005 20:09:46 -0000       1.130
+++ src/md5sum.c        11 Apr 2005 19:38:51 -0000
@@ -335,8 +335,9 @@ digest_file (const char *filename, bool 
 {
   FILE *fp;
   int err;
+  bool is_stdin = STREQ (filename, "-");
 
-  if (STREQ (filename, "-"))
+  if (is_stdin)
     {
       have_read_stdin = true;
       fp = stdin;
@@ -370,7 +371,7 @@ digest_file (const char *filename, bool 
       return false;
     }
 
-  if (fp != stdin && fclose (fp) == EOF)
+  if (!is_stdin && fclose (fp) != 0)
     {
       error (0, errno, "%s", filename);
       return false;
@@ -390,8 +391,9 @@ digest_check (const char *checkfile_name
   uintmax_t line_number;
   char *line;
   size_t line_chars_allocated;
+  bool is_stdin = STREQ (checkfile_name, "-");
 
-  if (STREQ (checkfile_name, "-"))
+  if (is_stdin)
     {
       have_read_stdin = true;
       checkfile_name = _("standard input");
@@ -505,7 +507,7 @@ digest_check (const char *checkfile_name
       return false;
     }
 
-  if (checkfile_stream != stdin && fclose (checkfile_stream) == EOF)
+  if (!is_stdin && fclose (checkfile_stream) != 0)
     {
       error (0, errno, "%s", checkfile_name);
       return false;
Index: src/nohup.c
===================================================================
RCS file: /fetish/cu/src/nohup.c,v
retrieving revision 1.21
diff -p -u -r1.21 nohup.c
--- src/nohup.c 5 Apr 2005 11:53:38 -0000       1.21
+++ src/nohup.c 11 Apr 2005 19:38:51 -0000
@@ -25,11 +25,12 @@
 
 #include "system.h"
 
+#include "cloexec.h"
 #include "error.h"
 #include "long-options.h"
 #include "path-concat.h"
 #include "quote.h"
-#include "cloexec.h"
+#include "unistd-safer.h"
 
 #define PROGRAM_NAME "nohup"
 
@@ -145,7 +146,7 @@ main (int argc, char **argv)
         if execve fails.  It's no big deal if this dup fails.  It might
         not change anything, and at worst, it'll lead to suppression of
         the post-failed-execve diagnostic.  */
-      saved_stderr_fd = dup (STDERR_FILENO);
+      saved_stderr_fd = dup_safer (STDERR_FILENO);
 
       if (0 <= saved_stderr_fd
          && set_cloexec_flag (saved_stderr_fd, true) != 0)
Index: src/od.c
===================================================================
RCS file: /fetish/cu/src/od.c,v
retrieving revision 1.153
diff -p -u -r1.153 od.c
--- src/od.c    17 Mar 2005 14:34:23 -0000      1.153
+++ src/od.c    11 Apr 2005 19:38:52 -0000
@@ -240,7 +240,7 @@ static size_t n_specs_allocated;
 static size_t bytes_per_block;
 
 /* Human-readable representation of *file_list (for error messages).
-   It differs from *file_list only when *file_list is "-".  */
+   It differs from file_list[-1] only when file_list[-1] is "-".  */
 static char const *input_filename;
 
 /* A NULL-terminated list of the file-arguments from the command line.  */
@@ -937,11 +937,11 @@ check_and_close (int in_errno)
       if (ferror (in_stream))
        {
          error (0, in_errno, _("%s: read error"), input_filename);
-         if (in_stream != stdin)
+         if (! STREQ (file_list[-1], "-"))
            fclose (in_stream);
          ok = false;
        }
-      else if (in_stream != stdin && fclose (in_stream) == EOF)
+      else if (! STREQ (file_list[-1], "-") && fclose (in_stream) != 0)
        {
          error (0, errno, "%s", input_filename);
          ok = false;
Index: src/paste.c
===================================================================
RCS file: /fetish/cu/src/paste.c,v
retrieving revision 1.78
diff -p -u -r1.78 paste.c
--- src/paste.c 28 Mar 2005 18:05:53 -0000      1.78
+++ src/paste.c 11 Apr 2005 19:38:52 -0000
@@ -336,7 +336,8 @@ paste_serial (size_t nfiles, char **fnam
   for (; nfiles; nfiles--, fnamptr++)
     {
       int saved_errno;
-      if (STREQ (*fnamptr, "-"))
+      bool is_stdin = STREQ (*fnamptr, "-");
+      if (is_stdin)
        {
          have_read_stdin = true;
          fileptr = stdin;
@@ -394,7 +395,7 @@ paste_serial (size_t nfiles, char **fnam
          error (0, saved_errno, "%s", *fnamptr);
          ok = false;
        }
-      if (fileptr == stdin)
+      if (is_stdin)
        clearerr (fileptr);     /* Also clear EOF. */
       else if (fclose (fileptr) == EOF)
        {
Index: src/pr.c
===================================================================
RCS file: /fetish/cu/src/pr.c,v
retrieving revision 1.142
diff -p -u -r1.142 pr.c
--- src/pr.c    9 Apr 2005 07:23:50 -0000       1.142
+++ src/pr.c    11 Apr 2005 19:38:52 -0000
@@ -320,6 +320,7 @@
 #include "inttostr.h"
 #include "mbswidth.h"
 #include "posixver.h"
+#include "stdio-safer.h"
 #include "strftime.h"
 #include "xstrtol.h"
 
@@ -1513,7 +1514,7 @@ open_file (char *name, COLUMN *p)
   else
     {
       p->name = name;
-      p->fp = fopen (name, "r");
+      p->fp = fopen_safer (name, "r");
     }
   if (p->fp == NULL)
     {
@@ -1543,7 +1544,7 @@ close_file (COLUMN *p)
     return;
   if (ferror (p->fp))
     error (EXIT_FAILURE, errno, "%s", p->name);
-  if (p->fp != stdin && fclose (p->fp) == EOF)
+  if (fileno (p->fp) != STDIN_FILENO && fclose (p->fp) != 0)
     error (EXIT_FAILURE, errno, "%s", p->name);
 
   if (!parallel_files)
Index: src/ptx.c
===================================================================
RCS file: /fetish/cu/src/ptx.c,v
retrieving revision 1.46
diff -p -u -r1.46 ptx.c
--- src/ptx.c   28 Mar 2005 18:08:12 -0000      1.46
+++ src/ptx.c   11 Apr 2005 19:38:53 -0000
@@ -2154,9 +2154,7 @@ Inc., 59 Temple Place - Suite 330, Bosto
 
       if (optind < argc)
        {
-         /* FIXME: don't fclose here? */
-         fclose (stdout);
-         if (fopen (argv[optind], "w") == NULL)
+         if (! freopen (argv[optind], "w", stdout))
            error (EXIT_FAILURE, errno, "%s", argv[optind]);
          optind++;
        }
Index: src/shred.c
===================================================================
RCS file: /fetish/cu/src/shred.c,v
retrieving revision 1.109
diff -p -u -r1.109 shred.c
--- src/shred.c 9 Apr 2005 04:57:15 -0000       1.109
+++ src/shred.c 11 Apr 2005 19:38:53 -0000
@@ -108,6 +108,7 @@
 #include "inttostr.h"
 #include "quotearg.h"          /* For quotearg_colon */
 #include "quote.h"             /* For quotearg_colon */
+#include "unistd-safer.h"
 
 #define DEFAULT_PASSES 25      /* Default */
 
@@ -1345,6 +1346,7 @@ wipename (char *oldname, char const *qol
   int dir_fd = open (dir, O_WRONLY | O_NOCTTY);
   if (dir_fd < 0)
     dir_fd = open (dir, O_RDONLY | O_NOCTTY);
+  dir_fd = fd_safer (dir_fd);
 
   if (flags->verbose)
     error (0, 0, _("%s: removing"), qoldname);
@@ -1434,32 +1436,11 @@ wipefile (char *name, char const *qname,
   int fd;
 
   fd = open (name, O_WRONLY | O_NOCTTY);
-  if (fd < 0)
-    {
-      if (errno == EACCES && flags->force)
-       {
-         if (chmod (name, S_IWUSR) >= 0) /* 0200, user-write-only */
-           fd = open (name, O_WRONLY | O_NOCTTY);
-       }
-      else if ((errno == ENOENT || errno == ENOTDIR)
-              && strncmp (name, "/dev/fd/", 8) == 0)
-       {
-         /* We accept /dev/fd/# even if the OS doesn't support it */
-         int errnum = errno;
-         unsigned long int num;
-         char *p;
-         errno = 0;
-         num = strtoul (name + 8, &p, 10);
-         /* If it's completely decimal with no leading zeros... */
-         if (errno == 0 && !*p && num <= INT_MAX &&
-             (('1' <= name[8] && name[8] <= '9')
-              || (name[8] == '0' && !name[9])))
-           {
-             return wipefd (num, qname, s, flags);
-           }
-         errno = errnum;
-       }
-    }
+  if (fd < 0
+      && (errno == EACCES && flags->force)
+      && chmod (name, S_IWUSR) == 0)
+    fd = open (name, O_WRONLY | O_NOCTTY);
+  fd = fd_safer (fd);
   if (fd < 0)
     {
       error (0, errno, _("%s: failed to open for writing"), qname);
Index: src/sort.c
===================================================================
RCS file: /fetish/cu/src/sort.c,v
retrieving revision 1.306
diff -p -u -r1.306 sort.c
--- src/sort.c  9 Apr 2005 04:57:37 -0000       1.306
+++ src/sort.c  11 Apr 2005 19:38:53 -0000
@@ -35,6 +35,7 @@
 #include "posixver.h"
 #include "quote.h"
 #include "stdio-safer.h"
+#include "unistd-safer.h"
 #include "xmemcoll.h"
 #include "xstrtol.h"
 
@@ -438,6 +439,7 @@ create_temp_file (FILE **pfp)
   sigprocmask (SIG_SETMASK, &oldset, NULL);
   errno = saved_errno;
 
+  fd = fd_safer (fd);
   if (fd < 0 || (*pfp = fdopen (fd, "w")) == NULL)
     die (_("cannot create temporary file"), file);
 
@@ -447,7 +449,8 @@ create_temp_file (FILE **pfp)
 /* Return a stream for FILE, opened with mode HOW.  A null FILE means
    standard output; HOW should be "w".  When opening for input, "-"
    means standard input.  To avoid confusion, do not return file
-   descriptors 0, 1, or 2.  */
+   descriptors STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO when
+   opening an ordinary FILE.  */
 
 static FILE *
 xfopen (const char *file, const char *how)
@@ -475,22 +478,24 @@ xfopen (const char *file, const char *ho
 static void
 xfclose (FILE *fp, char const *file)
 {
-  if (fp == stdin)
+  switch (fileno (fp))
     {
-      /* Allow reading stdin from tty more than once. */
+    case STDIN_FILENO:
+      /* Allow reading stdin from tty more than once.  */
       if (feof (fp))
        clearerr (fp);
-    }
-  else if (fp == stdout)
-    {
+      break;
+
+    case STDOUT_FILENO:
       /* Don't close stdout just yet.  close_stdout does that.  */
       if (fflush (fp) != 0)
        die (_("fflush failed"), file);
-    }
-  else
-    {
+      break;
+
+    default:
       if (fclose (fp) != 0)
        die (_("close failed"), file);
+      break;
     }
 }
 
@@ -1953,11 +1958,11 @@ avoid_trashing_input (char **files, size
 
   for (i = ntemps; i < nfiles; i++)
     {
-      bool standard_input = STREQ (files[i], "-");
+      bool is_stdin = STREQ (files[i], "-");
       bool same;
       struct stat instat;
 
-      if (outfile && STREQ (outfile, files[i]) && ! standard_input)
+      if (outfile && STREQ (outfile, files[i]) && !is_stdin)
        same = true;
       else
        {
@@ -1971,7 +1976,7 @@ avoid_trashing_input (char **files, size
              got_outstat = true;
            }
 
-         same = (((standard_input
+         same = (((is_stdin
                    ? fstat (STDIN_FILENO, &instat)
                    : stat (files[i], &instat))
                   == 0)
Index: src/split.c
===================================================================
RCS file: /fetish/cu/src/split.c,v
retrieving revision 1.104
diff -p -u -r1.104 split.c
--- src/split.c 25 Mar 2005 20:59:48 -0000      1.104
+++ src/split.c 11 Apr 2005 19:38:54 -0000
@@ -37,6 +37,7 @@
 #include "posixver.h"
 #include "quote.h"
 #include "safe-read.h"
+#include "unistd-safer.h"
 #include "xstrtol.h"
 
 /* The official name of this program (e.g., no `g' prefix).  */
@@ -212,8 +213,10 @@ cwrite (bool new_file_flag, const char *
       next_file_name ();
       if (verbose)
        fprintf (stderr, _("creating file `%s'\n"), outfile);
-      output_desc = open (outfile,
-                         O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+      output_desc = fd_safer (open (outfile,
+                                   O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+                                   (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
+                                    | S_IROTH | S_IWOTH)));
       if (output_desc < 0)
        error (EXIT_FAILURE, errno, "%s", outfile);
     }
Index: src/sum.c
===================================================================
RCS file: /fetish/cu/src/sum.c,v
retrieving revision 1.76
diff -p -u -r1.76 sum.c
--- src/sum.c   6 Mar 2005 16:32:23 -0000       1.76
+++ src/sum.c   11 Apr 2005 19:38:54 -0000
@@ -91,8 +91,9 @@ bsd_sum_file (const char *file, int prin
   uintmax_t total_bytes = 0;   /* The number of bytes. */
   int ch;              /* Each character read. */
   char hbuf[LONGEST_HUMAN_READABLE + 1];
+  bool is_stdin = STREQ (file, "-");
 
-  if (STREQ (file, "-"))
+  if (is_stdin)
     {
       fp = stdin;
       have_read_stdin = true;
@@ -120,12 +121,12 @@ bsd_sum_file (const char *file, int prin
   if (ferror (fp))
     {
       error (0, errno, "%s", file);
-      if (!STREQ (file, "-"))
+      if (!is_stdin)
        fclose (fp);
       return false;
     }
 
-  if (!STREQ (file, "-") && fclose (fp) == EOF)
+  if (!is_stdin && fclose (fp) != 0)
     {
       error (0, errno, "%s", file);
       return false;
@@ -158,9 +159,11 @@ sysv_sum_file (const char *file, int pri
   /* The sum of all the input bytes, modulo (UINT_MAX + 1).  */
   unsigned int s = 0;
 
-  if (STREQ (file, "-"))
+  bool is_stdin = STREQ (file, "-");
+
+  if (is_stdin)
     {
-      fd = 0;
+      fd = STDIN_FILENO;
       have_read_stdin = true;
     }
   else
@@ -186,7 +189,7 @@ sysv_sum_file (const char *file, int pri
       if (bytes_read == SAFE_READ_ERROR)
        {
          error (0, errno, "%s", file);
-         if (!STREQ (file, "-"))
+         if (!is_stdin)
            close (fd);
          return false;
        }
@@ -196,7 +199,7 @@ sysv_sum_file (const char *file, int pri
       total_bytes += bytes_read;
     }
 
-  if (!STREQ (file, "-") && close (fd) == -1)
+  if (!is_stdin && close (fd) != 0)
     {
       error (0, errno, "%s", file);
       return false;
Index: src/tac.c
===================================================================
RCS file: /fetish/cu/src/tac.c,v
retrieving revision 1.118
diff -p -u -r1.118 tac.c
--- src/tac.c   28 Mar 2005 18:11:18 -0000      1.118
+++ src/tac.c   11 Apr 2005 19:38:54 -0000
@@ -48,6 +48,7 @@ tac -r -s '.\|
 #include "quote.h"
 #include "quotearg.h"
 #include "safe-read.h"
+#include "unistd-safer.h"
 
 /* The official name of this program (e.g., no `g' prefix).  */
 #define PROGRAM_NAME "tac"
@@ -448,14 +449,13 @@ copy_to_temp (FILE **g_tmp, char **g_tem
 
   tempfile = template;
   fd = mkstemp (template);
-  if (fd == -1)
+  if (fd < 0)
     {
       error (0, errno, _("cannot create temporary file %s"), quote (tempfile));
       return false;
     }
 
-  tmp = fdopen (fd, "w+");
-  if (tmp == NULL)
+  if ((fd = fd_safer (fd)) < 0 || ! (tmp = fdopen (fd, "w+")))
     {
       error (0, errno, _("cannot open %s for writing"), quote (tempfile));
       close (fd);
@@ -521,8 +521,9 @@ tac_file (const char *filename)
   bool ok;
   off_t file_size;
   int fd;
+  bool is_stdin = STREQ (filename, "-");
 
-  if (STREQ (filename, "-"))
+  if (is_stdin)
     {
       have_read_stdin = true;
       fd = STDIN_FILENO;
@@ -554,7 +555,7 @@ tac_file (const char *filename)
        ? tac_seekable (fd, filename)
        : tac_nonseekable (fd, filename));
 
-  if (fd != STDIN_FILENO && close (fd) == -1)
+  if (!is_stdin && close (fd) != 0)
     {
       error (0, errno, _("%s: read error"), quotearg_colon (filename));
       ok = false;
Index: src/tail.c
===================================================================
RCS file: /fetish/cu/src/tail.c,v
retrieving revision 1.233
diff -p -u -r1.233 tail.c
--- src/tail.c  28 Mar 2005 18:18:21 -0000      1.233
+++ src/tail.c  11 Apr 2005 19:38:54 -0000
@@ -35,11 +35,11 @@
 #include "argmatch.h"
 #include "c-strtod.h"
 #include "error.h"
-#include "fcntl-safer.h"
 #include "inttostr.h"
 #include "posixver.h"
 #include "quote.h"
 #include "safe-read.h"
+#include "unistd-safer.h"
 #include "xnanosleep.h"
 #include "xstrtol.h"
 #include "xstrtod.h"
@@ -856,7 +856,8 @@ recheck (struct File_spec *f, bool block
   bool new_file;
   int fd = (is_stdin
            ? STDIN_FILENO
-           : open_safer (f->name, O_RDONLY | (blocking ? 0 : O_NONBLOCK)));
+           : fd_safer (open (f->name,
+                             O_RDONLY | (blocking ? 0 : O_NONBLOCK))));
 
   assert (valid_file_spec (f));
 
@@ -1286,7 +1287,7 @@ tail_file (struct File_spec *f, uintmax_
     }
   else
     {
-      fd = open_safer (f->name, O_RDONLY);
+      fd = fd_safer (open (f->name, O_RDONLY));
     }
 
   f->tailable = !(reopen_inaccessible_files && fd == -1);
Index: src/tee.c
===================================================================
RCS file: /fetish/cu/src/tee.c,v
retrieving revision 1.77
diff -p -u -r1.77 tee.c
--- src/tee.c   5 Apr 2005 11:40:53 -0000       1.77
+++ src/tee.c   11 Apr 2005 19:38:54 -0000
@@ -1,5 +1,5 @@
 /* tee - read from standard input and write to standard output and files.
-   Copyright (C) 85,1990-2004 Free Software Foundation, Inc.
+   Copyright (C) 85,1990-2005 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
@@ -25,6 +25,7 @@
 
 #include "system.h"
 #include "error.h"
+#include "stdio-safer.h"
 
 /* The official name of this program (e.g., no `g' prefix).  */
 #define PROGRAM_NAME "tee"
@@ -161,7 +162,7 @@ tee (int nfiles, const char **files)
     {
       descriptors[i] = (STREQ (files[i], "-")
                        ? stdout
-                       : fopen (files[i], mode_string));
+                       : fopen_safer (files[i], mode_string));
       if (descriptors[i] == NULL)
        {
          error (0, errno, "%s", files[i]);
Index: src/touch.c
===================================================================
RCS file: /fetish/cu/src/touch.c,v
retrieving revision 1.128
diff -p -u -r1.128 touch.c
--- src/touch.c 28 Mar 2005 18:13:40 -0000      1.128
+++ src/touch.c 11 Apr 2005 19:38:54 -0000
@@ -31,6 +31,7 @@
 #include "posixver.h"
 #include "quote.h"
 #include "safe-read.h"
+#include "unistd-safer.h"
 #include "utimens.h"
 
 /* The official name of this program (e.g., no `g' prefix).  */
@@ -128,6 +129,7 @@ touch (const char *file)
       /* Try to open FILE, creating it if necessary.  */
       fd = open (file, O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY,
                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+      fd = fd_safer (fd);
 
       /* Don't save a copy of errno if it's EISDIR, since that would lead
         touch to give a bogus diagnostic for e.g., `touch /' (assuming
Index: src/tsort.c
===================================================================
RCS file: /fetish/cu/src/tsort.c,v
retrieving revision 1.46
diff -p -u -r1.46 tsort.c
--- src/tsort.c 6 Mar 2005 16:33:28 -0000       1.46
+++ src/tsort.c 11 Apr 2005 19:38:54 -0000
@@ -63,9 +63,6 @@ struct item
 /* The name this program was run with. */
 char *program_name;
 
-/* True if any of the input files are the standard input. */
-static bool have_read_stdin;
-
 /* The head of the sorted list.  */
 static struct item *head = NULL;
 
@@ -442,30 +439,21 @@ tsort (const char *file)
   struct item *root;
   struct item *j = NULL;
   struct item *k = NULL;
-  FILE *fp;
   token_buffer tokenbuffer;
+  bool is_stdin = STREQ (file, "-");
 
   /* Intialize the head of the tree will hold the strings we're sorting.  */
   root = new_item (NULL);
 
-  if (STREQ (file, "-"))
-    {
-      fp = stdin;
-      have_read_stdin = true;
-    }
-  else
-    {
-      fp = fopen (file, "r");
-      if (fp == NULL)
-       error (EXIT_FAILURE, errno, "%s", file);
-    }
+  if (!is_stdin && ! freopen (file, "r", stdin))
+    error (EXIT_FAILURE, errno, "%s", file);
 
   init_tokenbuffer (&tokenbuffer);
 
   while (1)
     {
       /* T2. Next Relation.  */
-      size_t len = readtoken (fp, DELIM, sizeof (DELIM) - 1, &tokenbuffer);
+      size_t len = readtoken (stdin, DELIM, sizeof (DELIM) - 1, &tokenbuffer);
       if (len == (size_t) -1)
        break;
 
@@ -534,6 +522,10 @@ tsort (const char *file)
        }
     }
 
+  if (fclose (stdin) != 0)
+    error (EXIT_FAILURE, errno,
+          is_stdin ? _("standard input") : file);
+
   return ok;
 }
 
@@ -555,8 +547,6 @@ main (int argc, char **argv)
   if (getopt_long (argc, argv, "", NULL, NULL) != -1)
     usage (EXIT_FAILURE);
 
-  have_read_stdin = false;
-
   if (1 < argc - optind)
     {
       error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
@@ -565,8 +555,5 @@ main (int argc, char **argv)
 
   ok = tsort (optind == argc ? "-" : argv[optind]);
 
-  if (have_read_stdin && fclose (stdin) == EOF)
-    error (EXIT_FAILURE, errno, _("standard input"));
-
   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
 }
Index: src/unexpand.c
===================================================================
RCS file: /fetish/cu/src/unexpand.c,v
retrieving revision 1.88
diff -p -u -r1.88 unexpand.c
--- src/unexpand.c      25 Mar 2005 20:59:35 -0000      1.88
+++ src/unexpand.c      11 Apr 2005 19:38:54 -0000
@@ -257,7 +257,7 @@ next_file (FILE *fp)
          error (0, errno, "%s", prev_file);
          exit_status = EXIT_FAILURE;
        }
-      if (fp == stdin)
+      if (STREQ (prev_file, "-"))
        clearerr (fp);          /* Also clear EOF.  */
       else if (fclose (fp) != 0)
        {
@@ -268,7 +268,7 @@ next_file (FILE *fp)
 
   while ((file = *file_list++) != NULL)
     {
-      if (file[0] == '-' && file[1] == '\0')
+      if (STREQ (file, "-"))
        {
          have_read_stdin = true;
          prev_file = file;
Index: src/uniq.c
===================================================================
RCS file: /fetish/cu/src/uniq.c,v
retrieving revision 1.120
diff -p -u -r1.120 uniq.c
--- src/uniq.c  28 Mar 2005 18:14:15 -0000      1.120
+++ src/uniq.c  11 Apr 2005 19:38:54 -0000
@@ -30,6 +30,7 @@
 #include "hard-locale.h"
 #include "posixver.h"
 #include "quote.h"
+#include "stdio-safer.h"
 #include "xmemcoll.h"
 #include "xstrtol.h"
 #include "memcasecmp.h"
@@ -261,24 +262,22 @@ writeline (struct linebuffer const *line
 static void
 check_file (const char *infile, const char *outfile)
 {
-  FILE *istream;
   FILE *ostream;
   struct linebuffer lb1, lb2;
   struct linebuffer *thisline, *prevline;
+  bool is_stdin = STREQ (infile, "-");
+  bool is_stdout = STREQ (outfile, "-");
 
-  if (STREQ (infile, "-"))
-    istream = stdin;
-  else
-    istream = fopen (infile, "r");
-  if (istream == NULL)
+  if (!is_stdin && ! freopen (infile, "r", stdin))
     error (EXIT_FAILURE, errno, "%s", infile);
-
-  if (STREQ (outfile, "-"))
+  if (is_stdout)
     ostream = stdout;
   else
-    ostream = fopen (outfile, "w");
-  if (ostream == NULL)
-    error (EXIT_FAILURE, errno, "%s", outfile);
+    {
+      ostream = fopen_safer (outfile, "w");
+      if (! ostream)
+       error (EXIT_FAILURE, errno, "%s", outfile);
+    }
 
   thisline = &lb1;
   prevline = &lb2;
@@ -298,11 +297,11 @@ check_file (const char *infile, const ch
       char *prevfield IF_LINT (= NULL);
       size_t prevlen IF_LINT (= 0);
 
-      while (!feof (istream))
+      while (!feof (stdin))
        {
          char *thisfield;
          size_t thislen;
-         if (readlinebuffer (thisline, istream) == 0)
+         if (readlinebuffer (thisline, stdin) == 0)
            break;
          thisfield = find_field (thisline);
          thislen = thisline->length - 1 - (thisfield - thisline->buffer);
@@ -325,19 +324,19 @@ check_file (const char *infile, const ch
       uintmax_t match_count = 0;
       bool first_delimiter = true;
 
-      if (readlinebuffer (prevline, istream) == 0)
+      if (readlinebuffer (prevline, stdin) == 0)
        goto closefiles;
       prevfield = find_field (prevline);
       prevlen = prevline->length - 1 - (prevfield - prevline->buffer);
 
-      while (!feof (istream))
+      while (!feof (stdin))
        {
          bool match;
          char *thisfield;
          size_t thislen;
-         if (readlinebuffer (thisline, istream) == 0)
+         if (readlinebuffer (thisline, stdin) == 0)
            {
-             if (ferror (istream))
+             if (ferror (stdin))
                goto closefiles;
              break;
            }
@@ -384,18 +383,13 @@ check_file (const char *infile, const ch
     }
 
  closefiles:
-  if (ferror (istream) || fclose (istream) == EOF)
-    error (EXIT_FAILURE, errno, _("error reading %s"), infile);
+  if (ferror (stdin) || fclose (stdin) != 0)
+    error (EXIT_FAILURE, 0, _("error reading %s"), infile);
 
   /* Check for errors and close ostream only if it's not stdout --
      stdout is handled via the atexit-invoked close_stdout function.  */
-  if (ostream != stdout)
-    {
-      if (ferror (ostream))
-       error (EXIT_FAILURE, 0, _("error writing %s"), outfile);
-      if (ostream != stdout && fclose (ostream) != 0)
-       error (EXIT_FAILURE, errno, _("error writing %s"), outfile);
-    }
+  if (!is_stdout && (ferror (ostream) || fclose (ostream) != 0))
+    error (EXIT_FAILURE, 0, _("error writing %s"), outfile);
 
   free (lb1.buffer);
   free (lb2.buffer);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]