Mercurial > gnulib
annotate lib/freopen-safer.c @ 17363:5a51fb7777a9
sys_select, sys_time: port 2013-01-30 Solaris 2.6 fix to Cygwin
Problem reported by Marco Atzeri in
<http://lists.gnu.org/archive/html/bug-gnulib/2013-03/msg00000.html>.
* lib/sys_select.in.h [HAVE_SYS_SELECT_H && _CYGWIN_SYS_TIME_H]:
Simply delegate to the system <sys/select.h> in this case too.
Also, pay attention to _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H only
if OSF/1, since otherwise Cygwin breaks, and it doesn't seem to
be needed on Solaris either.
* lib/sys_time.in.h [_CYGWIN_SYS_TIME_H]:
Simply delgate to the system <sys/time.h> in this case.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Tue, 19 Mar 2013 09:08:47 -0700 |
parents | e542fd46ad6f |
children | 344018b6e5d7 |
rev | line source |
---|---|
12246 | 1 /* Invoke freopen, but avoid some glitches. |
2 | |
17249
e542fd46ad6f
maint: update all copyright year number ranges
Eric Blake <eblake@redhat.com>
parents:
16201
diff
changeset
|
3 Copyright (C) 2009-2013 Free Software Foundation, Inc. |
12246 | 4 |
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. | |
9 | |
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. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
17 | |
18 /* Written by Eric Blake. */ | |
19 | |
20 #include <config.h> | |
21 | |
22 #include "stdio-safer.h" | |
23 | |
24 #include <errno.h> | |
25 #include <fcntl.h> | |
26 #include <stdbool.h> | |
27 #include <unistd.h> | |
28 | |
29 /* Guarantee that FD is open; all smaller FDs must already be open. | |
30 Return true if successful. */ | |
31 static bool | |
32 protect_fd (int fd) | |
33 { | |
34 int value = open ("/dev/null", O_RDONLY); | |
35 if (value != fd) | |
36 { | |
37 if (0 <= value) | |
38 { | |
39 close (value); | |
40 errno = EBADF; /* Unexpected; this is as good as anything else. */ | |
41 } | |
42 return false; | |
43 } | |
44 return true; | |
45 } | |
46 | |
47 /* Like freopen, but guarantee that reopening stdin, stdout, or stderr | |
48 preserves the invariant that STDxxx_FILENO==fileno(stdxxx), and | |
49 that no other stream will interfere with the standard streams. | |
50 This is necessary because most freopen implementations will change | |
51 the associated fd of a stream to the lowest available slot. */ | |
52 | |
53 FILE * | |
54 freopen_safer (char const *name, char const *mode, FILE *f) | |
55 { | |
56 /* Unfortunately, we cannot use the fopen_safer approach of using | |
57 fdopen (dup_safer (fileno (freopen (cmd, mode, f)))), because we | |
58 need to return f itself. The implementation of freopen(NULL,m,f) | |
59 is system-dependent, so the best we can do is guarantee that all | |
60 lower-valued standard fds are open prior to the freopen call, | |
61 even though this puts more pressure on open fds. */ | |
62 bool protect_in = false; | |
63 bool protect_out = false; | |
64 bool protect_err = false; | |
65 int saved_errno; | |
66 | |
67 switch (fileno (f)) | |
68 { | |
69 default: /* -1 or not a standard stream. */ | |
70 if (dup2 (STDERR_FILENO, STDERR_FILENO) != STDERR_FILENO) | |
71 protect_err = true; | |
72 /* fall through */ | |
73 case STDERR_FILENO: | |
74 if (dup2 (STDOUT_FILENO, STDOUT_FILENO) != STDOUT_FILENO) | |
75 protect_out = true; | |
76 /* fall through */ | |
77 case STDOUT_FILENO: | |
78 if (dup2 (STDIN_FILENO, STDIN_FILENO) != STDIN_FILENO) | |
79 protect_in = true; | |
80 /* fall through */ | |
81 case STDIN_FILENO: | |
82 /* Nothing left to protect. */ | |
83 break; | |
84 } | |
85 if (protect_in && !protect_fd (STDIN_FILENO)) | |
86 f = NULL; | |
87 else if (protect_out && !protect_fd (STDOUT_FILENO)) | |
88 f = NULL; | |
89 else if (protect_err && !protect_fd (STDERR_FILENO)) | |
90 f = NULL; | |
91 else | |
92 f = freopen (name, mode, f); | |
93 saved_errno = errno; | |
94 if (protect_err) | |
95 close (STDERR_FILENO); | |
96 if (protect_out) | |
97 close (STDOUT_FILENO); | |
98 if (protect_in) | |
99 close (STDIN_FILENO); | |
100 if (!f) | |
101 errno = saved_errno; | |
102 return f; | |
103 } |