@@ -10,8 +10,6 @@ Date: August 2012
10
10
11
11
#include " run.h"
12
12
13
- #include < cassert>
14
-
15
13
#ifdef _WIN32
16
14
#include < process.h>
17
15
#else
@@ -30,6 +28,7 @@ Date: August 2012
30
28
31
29
#endif
32
30
31
+ #include < util/invariant.h>
33
32
#include < util/unicode.h>
34
33
#include < util/signal_catcher.h>
35
34
@@ -39,19 +38,59 @@ int run_shell(const std::string &command)
39
38
std::vector<std::string> argv;
40
39
argv.push_back (shell);
41
40
argv.push_back (command);
42
- return run (shell, argv, " " , " " );
41
+ return run (shell, argv, " " , " " , " " );
42
+ }
43
+
44
+ #ifndef _WIN32
45
+ // / open given file to replace either stdin, stderr, stdout
46
+ static int stdio_redirection (int fd, const std::string &file)
47
+ {
48
+ int result_fd = fd;
49
+
50
+ if (file.empty ())
51
+ return result_fd;
52
+
53
+ int flags = 0 , mode = 0 ;
54
+ std::string name;
55
+
56
+ switch (fd)
57
+ {
58
+ case STDIN_FILENO:
59
+ flags = O_RDONLY;
60
+ name = " stdin" ;
61
+ break ;
62
+
63
+ case STDOUT_FILENO:
64
+ case STDERR_FILENO:
65
+ flags = O_CREAT | O_WRONLY;
66
+ mode = S_IRUSR | S_IWUSR;
67
+ name = fd == STDOUT_FILENO ? " stdout" : " stderr" ;
68
+ break ;
69
+
70
+ default :
71
+ UNREACHABLE;
72
+ }
73
+
74
+ result_fd = open (file.c_str (), flags, mode);
75
+ if (result_fd == -1 )
76
+ perror ((" Failed to open " + name + " file " + file).c_str ());
77
+
78
+ return result_fd;
43
79
}
80
+ #endif
44
81
45
82
int run (
46
83
const std::string &what,
47
84
const std::vector<std::string> &argv,
48
85
const std::string &std_input,
49
- const std::string &std_output)
86
+ const std::string &std_output,
87
+ const std::string &std_error)
50
88
{
51
89
#ifdef _WIN32
52
- // we don't support stdin/stdout redirection on Windows
53
- assert (std_input.empty ());
54
- assert (std_output.empty ());
90
+ // we don't support stdin/stdout/stderr redirection on Windows
91
+ PRECONDITION (std_input.empty ());
92
+ PRECONDITION (std_output.empty ());
93
+ PRECONDITION (std_error.empty ());
55
94
56
95
// unicode version of the arguments
57
96
std::vector<std::wstring> wargv;
@@ -77,29 +116,9 @@ int run(
77
116
return status;
78
117
79
118
#else
80
- int stdin_fd=STDIN_FILENO;
81
-
82
- if (!std_input.empty ())
83
- {
84
- stdin_fd=open (std_input.c_str (), O_RDONLY);
85
- if (stdin_fd==-1 )
86
- {
87
- perror (" Failed to open stdin copy" );
88
- return 1 ;
89
- }
90
- }
91
-
92
- int stdout_fd=STDOUT_FILENO;
93
-
94
- if (!std_output.empty ())
95
- {
96
- stdout_fd=open (std_output.c_str (), O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
97
- if (stdout_fd==-1 )
98
- {
99
- perror (" Failed to open stdout copy" );
100
- return 1 ;
101
- }
102
- }
119
+ int stdin_fd = stdio_redirection (STDIN_FILENO, std_input);
120
+ int stdout_fd = stdio_redirection (STDOUT_FILENO, std_input);
121
+ int stderr_fd = stdio_redirection (STDERR_FILENO, std_error);
103
122
104
123
// temporarily suspend all signals
105
124
sigset_t new_mask, old_mask;
@@ -127,6 +146,8 @@ int run(
127
146
dup2 (stdin_fd, STDIN_FILENO);
128
147
if (stdout_fd!=STDOUT_FILENO)
129
148
dup2 (stdout_fd, STDOUT_FILENO);
149
+ if (stderr_fd != STDERR_FILENO)
150
+ dup2 (stderr_fd, STDERR_FILENO);
130
151
131
152
errno=0 ;
132
153
execvp (what.c_str (), _argv.data ());
@@ -153,13 +174,17 @@ int run(
153
174
close (stdin_fd);
154
175
if (stdout_fd!=STDOUT_FILENO)
155
176
close (stdout_fd);
177
+ if (stderr_fd != STDERR_FILENO)
178
+ close (stderr_fd);
156
179
return 1 ;
157
180
}
158
181
159
182
if (stdin_fd!=STDIN_FILENO)
160
183
close (stdin_fd);
161
184
if (stdout_fd!=STDOUT_FILENO)
162
185
close (stdout_fd);
186
+ if (stderr_fd != STDERR_FILENO)
187
+ close (stderr_fd);
163
188
164
189
return WEXITSTATUS (status);
165
190
}
@@ -173,6 +198,8 @@ int run(
173
198
close (stdin_fd);
174
199
if (stdout_fd!=STDOUT_FILENO)
175
200
close (stdout_fd);
201
+ if (stderr_fd != STDERR_FILENO)
202
+ close (stderr_fd);
176
203
177
204
return 1 ;
178
205
}
0 commit comments