15 #include <util/pragma_push.def> 
   17 #pragma warning(disable:4668) 
   19 #pragma warning(disable:5039) 
   24 #include <util/pragma_pop.def> 
   48 int run(
const std::string &what, 
const std::vector<std::string> &argv)
 
   50   return run(what, argv, 
"", 
"", 
"");
 
   54 #define STDIN_FILENO 0 
   55 #define STDOUT_FILENO 1 
   56 #define STDERR_FILENO 2 
   66   fdt result_fd = INVALID_HANDLE_VALUE;
 
   69   SECURITY_ATTRIBUTES SecurityAttributes;
 
   70   ZeroMemory(&SecurityAttributes, 
sizeof SecurityAttributes);
 
   71   SecurityAttributes.bInheritHandle = 
true;
 
   78       result_fd = GetStdHandle(STD_INPUT_HANDLE);
 
   80       result_fd = CreateFileW(
 
   86         FILE_ATTRIBUTE_READONLY,
 
   93       result_fd = GetStdHandle(STD_OUTPUT_HANDLE);
 
   95       result_fd = CreateFileW(
 
  101         FILE_ATTRIBUTE_NORMAL,
 
  108       result_fd = GetStdHandle(STD_ERROR_HANDLE);
 
  110       result_fd = CreateFileW(
 
  116         FILE_ATTRIBUTE_NORMAL,
 
  124   if(result_fd == INVALID_HANDLE_VALUE)
 
  125     perror((
"Failed to open " + name + 
" file " + file).c_str());
 
  132   int flags = 0, mode = 0;
 
  144     flags = O_CREAT | O_WRONLY;
 
  145     mode = S_IRUSR | S_IWUSR;
 
  146     name = fd == STDOUT_FILENO ? 
"stdout" : 
"stderr";
 
  153   const fdt result_fd = open(file.c_str(), flags, mode);
 
  156     perror((
"Failed to open " + name + 
" file " + file).c_str());
 
  165 std::wstring quote_windows_arg(
const std::wstring &src)
 
  168   if(src.find_first_of(L
" \t\n\v\"") == src.npos && !src.empty())
 
  171   std::wstring result = L
"\"";
 
  173   for(
auto it = src.begin();; ++it)
 
  175     std::size_t NumberBackslashes = 0;
 
  177     while(it != src.end() && *it == L
'\\')
 
  191       result.append(NumberBackslashes * 2, L
'\\');
 
  201       result.append(NumberBackslashes * 2 + 1, L
'\\');
 
  202       result.push_back(*it);
 
  210       result.append(NumberBackslashes, L
'\\');
 
  211       result.push_back(*it);
 
  215   result.push_back(L
'"');
 
  225 std::string get_last_error_as_string()
 
  228   DWORD error_message_id = GetLastError();
 
  229   if(error_message_id == 0)
 
  232   LPWSTR message_buffer = 
nullptr;
 
  233   std::size_t size = FormatMessageW(
 
  234     FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
 
  235       FORMAT_MESSAGE_IGNORE_INSERTS,
 
  238     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 
  239     (LPWSTR)&message_buffer,
 
  243   std::wstring message(message_buffer, size);
 
  246   LocalFree(message_buffer);
 
  253   const std::string &what,
 
  254   const std::vector<std::string> &argv,
 
  255   const std::string &std_input,
 
  256   const std::string &std_output,
 
  257   const std::string &std_error)
 
  261   std::wstring cmdline;
 
  264   cmdline = quote_windows_arg(
widen(what));
 
  266   for(std::size_t i = 1; i < argv.size(); i++)
 
  269     cmdline += quote_windows_arg(
widen(argv[i]));
 
  272   PROCESS_INFORMATION piProcInfo;
 
  273   STARTUPINFOW siStartInfo;
 
  275   ZeroMemory(&piProcInfo, 
sizeof piProcInfo);
 
  276   ZeroMemory(&siStartInfo, 
sizeof siStartInfo);
 
  278   siStartInfo.cb = 
sizeof siStartInfo;
 
  284   siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
 
  287   std::vector<wchar_t> mutable_cmdline(cmdline.begin(), cmdline.end());
 
  288   mutable_cmdline.push_back(0); 
 
  289   wchar_t *cmdline_ptr = mutable_cmdline.data();
 
  291   BOOL bSuccess = CreateProcessW(
 
  306     std::string windows_error = get_last_error_as_string();
 
  308     if(!std_input.empty())
 
  309       CloseHandle(siStartInfo.hStdInput);
 
  310     if(!std_output.empty())
 
  311       CloseHandle(siStartInfo.hStdOutput);
 
  312     if(!std_error.empty())
 
  313       CloseHandle(siStartInfo.hStdError);
 
  316     std::ofstream stderr_stream(std_error);
 
  317     stderr_stream << windows_error;
 
  323   WaitForSingleObject(piProcInfo.hProcess, INFINITE);
 
  325   if(!std_input.empty())
 
  326     CloseHandle(siStartInfo.hStdInput);
 
  327   if(!std_output.empty())
 
  328     CloseHandle(siStartInfo.hStdOutput);
 
  329   if(!std_error.empty())
 
  330     CloseHandle(siStartInfo.hStdError);
 
  335   if(!GetExitCodeProcess(piProcInfo.hProcess, &exit_code))
 
  337     CloseHandle(piProcInfo.hProcess);
 
  338     CloseHandle(piProcInfo.hThread);
 
  342   CloseHandle(piProcInfo.hProcess);
 
  343   CloseHandle(piProcInfo.hThread);
 
  352   if(stdin_fd == -1 || stdout_fd == -1 || stderr_fd == -1)
 
  356   sigset_t new_mask, old_mask;
 
  357   sigemptyset(&new_mask);
 
  358   sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
 
  361   pid_t childpid = fork();
 
  369       sigprocmask(SIG_SETMASK, &old_mask, 
nullptr);
 
  371       std::vector<char *> _argv(argv.size()+1);
 
  372       for(std::size_t i=0; i<argv.size(); i++)
 
  373         _argv[i]=strdup(argv[i].c_str());
 
  375       _argv[argv.size()]=
nullptr;
 
  377       if(stdin_fd!=STDIN_FILENO)
 
  378         dup2(stdin_fd, STDIN_FILENO);
 
  379       if(stdout_fd!=STDOUT_FILENO)
 
  380         dup2(stdout_fd, STDOUT_FILENO);
 
  381       if(stderr_fd != STDERR_FILENO)
 
  382         dup2(stderr_fd, STDERR_FILENO);
 
  385       execvp(what.c_str(), _argv.data());
 
  388       perror(std::string(
"execvp "+what+
" failed").c_str());
 
  397       sigprocmask(SIG_SETMASK, &old_mask, 
nullptr);
 
  402       while(waitpid(childpid, &status, 0)==-1)
 
  410           perror(
"Waiting for child process failed");
 
  411           if(stdin_fd!=STDIN_FILENO)
 
  413           if(stdout_fd!=STDOUT_FILENO)
 
  415           if(stderr_fd != STDERR_FILENO)
 
  423       if(stdin_fd!=STDIN_FILENO)
 
  425       if(stdout_fd!=STDOUT_FILENO)
 
  427       if(stderr_fd != STDERR_FILENO)
 
  430       return WEXITSTATUS(status);
 
  436     sigprocmask(SIG_SETMASK, &old_mask, 
nullptr);
 
  438     if(stdin_fd!=STDIN_FILENO)
 
  440     if(stdout_fd!=STDOUT_FILENO)
 
  442     if(stderr_fd != STDERR_FILENO)
 
  456   if(src.find(
' ')==std::string::npos &&
 
  457      src.find(
'"')==std::string::npos &&
 
  458      src.find(
'&')==std::string::npos &&
 
  459      src.find(
'|')==std::string::npos &&
 
  460      src.find(
'(')==std::string::npos &&
 
  461      src.find(
')')==std::string::npos &&
 
  462      src.find(
'<')==std::string::npos &&
 
  463      src.find(
'>')==std::string::npos &&
 
  464      src.find(
'^')==std::string::npos)
 
  474   for(
const char ch : src)
 
  489   if(src.find(
' ')==std::string::npos &&
 
  490      src.find(
'"')==std::string::npos &&
 
  491      src.find(
'*')==std::string::npos &&
 
  492      src.find(
'$')==std::string::npos &&
 
  493      src.find(
'\\')==std::string::npos &&
 
  494      src.find(
'?')==std::string::npos &&
 
  495      src.find(
'&')==std::string::npos &&
 
  496      src.find(
'|')==std::string::npos &&
 
  497      src.find(
'>')==std::string::npos &&
 
  498      src.find(
'<')==std::string::npos &&
 
  499      src.find(
'^')==std::string::npos &&
 
  500      src.find(
'\'')==std::string::npos)
 
  511   for(
const char ch : src)
 
  525   const std::string &what,
 
  526   const std::vector<std::string> &argv,
 
  527   const std::string &std_input,
 
  528   std::ostream &std_output,
 
  529   const std::string &std_error)
 
  534   int result = 
run(what, argv, std_input, tmpi(), std_error);
 
  536   std::ifstream instream(tmpi());
 
  539     std_output << instream.rdbuf(); 
 
  548   for(
const auto &arg : argv)
 
  559   if(!std_input.empty())
 
  562   if(!std_error.empty())
 
  565   FILE *stream=popen(command.c_str(), 
"r");
 
  570     while((ch=fgetc(stream))!=EOF)
 
  571       std_output << (
unsigned char)ch;
 
  573     int result = pclose(stream);
 
  574     return WEXITSTATUS(result);