@@ -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,12 @@ int run(
77
116
return status;
78
117
79
118
#else
80
- int stdin_fd=STDIN_FILENO;
119
+ int stdin_fd = stdio_redirection (STDIN_FILENO, std_input);
120
+ int stdout_fd = stdio_redirection (STDOUT_FILENO, std_output);
121
+ int stderr_fd = stdio_redirection (STDERR_FILENO, std_error);
81
122
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
- }
123
+ if (stdin_fd == -1 || stdout_fd == -1 || stderr_fd == -1 )
124
+ return 1 ;
103
125
104
126
// temporarily suspend all signals
105
127
sigset_t new_mask, old_mask;
@@ -127,6 +149,8 @@ int run(
127
149
dup2 (stdin_fd, STDIN_FILENO);
128
150
if (stdout_fd!=STDOUT_FILENO)
129
151
dup2 (stdout_fd, STDOUT_FILENO);
152
+ if (stderr_fd != STDERR_FILENO)
153
+ dup2 (stderr_fd, STDERR_FILENO);
130
154
131
155
errno=0 ;
132
156
execvp (what.c_str (), _argv.data ());
@@ -153,13 +177,17 @@ int run(
153
177
close (stdin_fd);
154
178
if (stdout_fd!=STDOUT_FILENO)
155
179
close (stdout_fd);
180
+ if (stderr_fd != STDERR_FILENO)
181
+ close (stderr_fd);
156
182
return 1 ;
157
183
}
158
184
159
185
if (stdin_fd!=STDIN_FILENO)
160
186
close (stdin_fd);
161
187
if (stdout_fd!=STDOUT_FILENO)
162
188
close (stdout_fd);
189
+ if (stderr_fd != STDERR_FILENO)
190
+ close (stderr_fd);
163
191
164
192
return WEXITSTATUS (status);
165
193
}
@@ -173,6 +201,8 @@ int run(
173
201
close (stdin_fd);
174
202
if (stdout_fd!=STDOUT_FILENO)
175
203
close (stdout_fd);
204
+ if (stderr_fd != STDERR_FILENO)
205
+ close (stderr_fd);
176
206
177
207
return 1 ;
178
208
}
0 commit comments