1 /* Invoke freopen, but avoid some glitches.
3 Copyright (C) 2009-2017 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Written by Eric Blake. */
22 #include "stdio-safer.h"
31 # define FALLTHROUGH ((void) 0)
33 # define FALLTHROUGH __attribute__ ((__fallthrough__))
37 /* Guarantee that FD is open; all smaller FDs must already be open.
38 Return true if successful. */
42 int value
= open ("/dev/null", O_RDONLY
);
48 errno
= EBADF
; /* Unexpected; this is as good as anything else. */
55 /* Like freopen, but guarantee that reopening stdin, stdout, or stderr
56 preserves the invariant that STDxxx_FILENO==fileno(stdxxx), and
57 that no other stream will interfere with the standard streams.
58 This is necessary because most freopen implementations will change
59 the associated fd of a stream to the lowest available slot. */
62 freopen_safer (char const *name
, char const *mode
, FILE *f
)
64 /* Unfortunately, we cannot use the fopen_safer approach of using
65 fdopen (dup_safer (fileno (freopen (cmd, mode, f)))), because we
66 need to return f itself. The implementation of freopen(NULL,m,f)
67 is system-dependent, so the best we can do is guarantee that all
68 lower-valued standard fds are open prior to the freopen call,
69 even though this puts more pressure on open fds. */
70 bool protect_in
= false;
71 bool protect_out
= false;
72 bool protect_err
= false;
77 default: /* -1 or not a standard stream. */
78 if (dup2 (STDERR_FILENO
, STDERR_FILENO
) != STDERR_FILENO
)
82 if (dup2 (STDOUT_FILENO
, STDOUT_FILENO
) != STDOUT_FILENO
)
86 if (dup2 (STDIN_FILENO
, STDIN_FILENO
) != STDIN_FILENO
)
90 /* Nothing left to protect. */
93 if (protect_in
&& !protect_fd (STDIN_FILENO
))
95 else if (protect_out
&& !protect_fd (STDOUT_FILENO
))
97 else if (protect_err
&& !protect_fd (STDERR_FILENO
))
100 f
= freopen (name
, mode
, f
);
103 close (STDERR_FILENO
);
105 close (STDOUT_FILENO
);
107 close (STDIN_FILENO
);