15 #include <util/pragma_push.def>
17 #pragma warning(disable:4668)
22 #include <util/pragma_pop.def>
34 #include <sys/types.h>
47 int run(
const std::string &what,
const std::vector<std::string> &argv)
49 return run(what, argv,
"",
"",
"");
53 #define STDIN_FILENO 0
54 #define STDOUT_FILENO 1
55 #define STDERR_FILENO 2
65 fdt result_fd = INVALID_HANDLE_VALUE;
68 SECURITY_ATTRIBUTES SecurityAttributes;
69 ZeroMemory(&SecurityAttributes,
sizeof SecurityAttributes);
70 SecurityAttributes.bInheritHandle =
true;
77 result_fd = GetStdHandle(STD_INPUT_HANDLE);
79 result_fd = CreateFileW(
85 FILE_ATTRIBUTE_READONLY,
92 result_fd = GetStdHandle(STD_OUTPUT_HANDLE);
94 result_fd = CreateFileW(
100 FILE_ATTRIBUTE_NORMAL,
107 result_fd = GetStdHandle(STD_ERROR_HANDLE);
109 result_fd = CreateFileW(
115 FILE_ATTRIBUTE_NORMAL,
123 if(result_fd == INVALID_HANDLE_VALUE)
124 perror((
"Failed to open " + name +
" file " +
file).c_str());
131 int flags = 0, mode = 0;
143 flags = O_CREAT | O_WRONLY;
144 mode = S_IRUSR | S_IWUSR;
145 name = fd == STDOUT_FILENO ?
"stdout" :
"stderr";
152 const fdt result_fd = open(
file.c_str(), flags, mode);
155 perror((
"Failed to open " + name +
" file " +
file).c_str());
164 std::wstring quote_windows_arg(
const std::wstring &src)
166 if(src.find_first_of(L
" \t\n\v\"") == src.npos)
169 std::wstring result = L
"\"";
171 for(
auto it = src.begin();; ++it)
173 std::size_t NumberBackslashes = 0;
175 while(it != src.end() && *it == L
'\\')
189 result.append(NumberBackslashes * 2, L
'\\');
199 result.append(NumberBackslashes * 2 + 1, L
'\\');
200 result.push_back(*it);
208 result.append(NumberBackslashes, L
'\\');
209 result.push_back(*it);
213 result.push_back(L
'"');
220 const std::string &what,
221 const std::vector<std::string> &argv,
222 const std::string &std_input,
223 const std::string &std_output,
224 const std::string &std_error)
228 std::wstring cmdline;
231 cmdline = quote_windows_arg(
widen(what));
233 for(std::size_t i = 1; i < argv.size(); i++)
236 cmdline += quote_windows_arg(
widen(argv[i]));
239 PROCESS_INFORMATION piProcInfo;
240 STARTUPINFOW siStartInfo;
242 ZeroMemory(&piProcInfo,
sizeof piProcInfo);
243 ZeroMemory(&siStartInfo,
sizeof siStartInfo);
245 siStartInfo.cb =
sizeof siStartInfo;
251 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
254 std::vector<wchar_t> mutable_cmdline(cmdline.begin(), cmdline.end());
255 mutable_cmdline.push_back(0);
256 wchar_t *cmdline_ptr = mutable_cmdline.data();
258 BOOL bSuccess = CreateProcessW(
272 if(!std_input.empty())
273 CloseHandle(siStartInfo.hStdInput);
274 if(!std_output.empty())
275 CloseHandle(siStartInfo.hStdOutput);
276 if(!std_error.empty())
277 CloseHandle(siStartInfo.hStdError);
282 WaitForSingleObject(piProcInfo.hProcess, INFINITE);
284 if(!std_input.empty())
285 CloseHandle(siStartInfo.hStdInput);
286 if(!std_output.empty())
287 CloseHandle(siStartInfo.hStdOutput);
288 if(!std_error.empty())
289 CloseHandle(siStartInfo.hStdError);
294 if(!GetExitCodeProcess(piProcInfo.hProcess, &exit_code))
296 CloseHandle(piProcInfo.hProcess);
297 CloseHandle(piProcInfo.hThread);
301 CloseHandle(piProcInfo.hProcess);
302 CloseHandle(piProcInfo.hThread);
311 if(stdin_fd == -1 || stdout_fd == -1 || stderr_fd == -1)
315 sigset_t new_mask, old_mask;
316 sigemptyset(&new_mask);
317 sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
320 pid_t childpid = fork();
328 sigprocmask(SIG_SETMASK, &old_mask,
nullptr);
330 std::vector<char *> _argv(argv.size()+1);
331 for(std::size_t i=0; i<argv.size(); i++)
332 _argv[i]=strdup(argv[i].c_str());
334 _argv[argv.size()]=
nullptr;
336 if(stdin_fd!=STDIN_FILENO)
337 dup2(stdin_fd, STDIN_FILENO);
338 if(stdout_fd!=STDOUT_FILENO)
339 dup2(stdout_fd, STDOUT_FILENO);
340 if(stderr_fd != STDERR_FILENO)
341 dup2(stderr_fd, STDERR_FILENO);
344 execvp(what.c_str(), _argv.data());
347 perror(std::string(
"execvp "+what+
" failed").c_str());
356 sigprocmask(SIG_SETMASK, &old_mask,
nullptr);
361 while(waitpid(childpid, &status, 0)==-1)
369 perror(
"Waiting for child process failed");
370 if(stdin_fd!=STDIN_FILENO)
372 if(stdout_fd!=STDOUT_FILENO)
374 if(stderr_fd != STDERR_FILENO)
382 if(stdin_fd!=STDIN_FILENO)
384 if(stdout_fd!=STDOUT_FILENO)
386 if(stderr_fd != STDERR_FILENO)
389 return WEXITSTATUS(status);
395 sigprocmask(SIG_SETMASK, &old_mask,
nullptr);
397 if(stdin_fd!=STDIN_FILENO)
399 if(stdout_fd!=STDOUT_FILENO)
401 if(stderr_fd != STDERR_FILENO)
415 if(src.find(
' ')==std::string::npos &&
416 src.find(
'"')==std::string::npos &&
417 src.find(
'&')==std::string::npos &&
418 src.find(
'|')==std::string::npos &&
419 src.find(
'(')==std::string::npos &&
420 src.find(
')')==std::string::npos &&
421 src.find(
'<')==std::string::npos &&
422 src.find(
'>')==std::string::npos &&
423 src.find(
'^')==std::string::npos)
433 for(
const char ch : src)
448 if(src.find(
' ')==std::string::npos &&
449 src.find(
'"')==std::string::npos &&
450 src.find(
'*')==std::string::npos &&
451 src.find(
'$')==std::string::npos &&
452 src.find(
'\\')==std::string::npos &&
453 src.find(
'?')==std::string::npos &&
454 src.find(
'&')==std::string::npos &&
455 src.find(
'|')==std::string::npos &&
456 src.find(
'>')==std::string::npos &&
457 src.find(
'<')==std::string::npos &&
458 src.find(
'^')==std::string::npos &&
459 src.find(
'\'')==std::string::npos)
470 for(
const char ch : src)
484 const std::string &what,
485 const std::vector<std::string> &argv,
486 const std::string &std_input,
487 std::ostream &std_output,
488 const std::string &std_error)
493 int result =
run(what, argv, std_input, tmpi(), std_error);
495 std::ifstream instream(tmpi());
498 std_output << instream.rdbuf();
507 for(
const auto &arg : argv)
518 if(!std_input.empty())
521 if(!std_error.empty())
524 FILE *stream=popen(command.c_str(),
"r");
529 while((ch=fgetc(stream))!=EOF)
530 std_output << (
unsigned char)ch;
532 return pclose(stream);