1/*******************************************************************\
9\*******************************************************************/
15#include <util/pragma_push.def>
17#pragma warning(disable:4668)
18 // using #if/#elif on undefined macro
19#pragma warning(disable:5039)
20// pointer or reference to potentially throwing function passed to extern C
24#include <util/pragma_pop.def>
49 int run(
const std::string &what,
const std::vector<std::string> &argv)
51 return run(what, argv,
"",
"",
"");
56#define STDOUT_FILENO 1
57#define STDERR_FILENO 2
126 perror((
"Failed to open " + name +
" file " + file).c_str());
133 int flags = 0, mode = 0;
157 perror((
"Failed to open " + name +
" file " + file).c_str());
165// https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
168 // note that an empty argument requires quotes
169 if(src.find_first_of(
L " \t\n\v\"") == src.npos && !src.empty())
172 std::wstring result =
L "\"";
174 for(
auto it = src.begin();; ++it)
178 while(it != src.end() && *it ==
L '\\')
187 // Escape all backslashes, but let the terminating
188 // double quotation mark we add below be interpreted
189 // as a metacharacter.
195 else if(*it ==
L '"')
198 // Escape all backslashes and the following
199 // double quotation mark.
203 result.push_back(*it);
208 // Backslashes aren't special here.
212 result.push_back(*it);
216 result.push_back(
L '"');
223// https://stackoverflow.com/a/17387176
224// Returns the last Win32 error, in string format. Returns an empty string if
228 // Get the error message, if any.
254 const std::string &what,
255 const std::vector<std::string> &argv,
261 // unicode commandline, quoted
262 std::wstring cmdline;
264 // we replace argv[0] by what
267 for(std::size_t i = 1; i < argv.size(); i++)
287 // CreateProcessW wants to modify the command line
293 NULL,
// application name
295 NULL,
// process security attributes
296 NULL,
// primary thread security attributes
297 true,
// handles are inherited
299 NULL,
// use parent's environment
300 NULL,
// use parent's current directory
306 // obtain the error message before doing further system calls
316 // now re-open the file and write the above error message
323 // wait for child to finish
356 // temporarily suspend all signals
361 /* now create new process */
364 if(
childpid>=0)
/* fork succeeded */
366 if(
childpid==0)
/* fork() returns 0 to the child process */
372 std::vector<char *>
_argv(argv.size()+1);
373 for(std::size_t i=0; i<argv.size(); i++)
376 _argv[argv.size()]=
nullptr;
388 /* usually no return */
389 perror(std::string(
"execvp "+what+
" failed").c_str());
392 else /* fork() returns new pid to the parent process */
394 // must do before resuming signals to avoid race
400 int status;
/* parent process: child's exit status */
402 /* wait for child to exit, and store its status */
406 continue;
// try again
411 perror(
"Waiting for child process failed");
434 else /* fork returns -1 on failure */
455 // first check if quoting is needed at all
457 if(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 &&
465 src.find(
'^')==std::string::npos)
467 // seems fine -- return as is
475 for(
const char ch : src)
478 result+=
'"';
// quotes are doubled
488 // first check if quoting is needed at all
503 // seems fine -- return as is
509 // the single quotes catch everything but themselves!
512 for(
const char ch : src)
526 const std::string &what,
527 const std::vector<std::string> &argv,
555 // temporarily suspend all signals
560 /* now create new process */
563 if(
childpid >= 0)
/* fork succeeded */
565 if(
childpid == 0)
/* fork() returns 0 to the child process */
573 std::vector<char *>
_argv(argv.size() + 1);
574 for(std::size_t i = 0; i < argv.size(); i++)
577 _argv[argv.size()] =
nullptr;
589 /* usually no return */
590 perror(std::string(
"execvp " + what +
" failed").c_str());
593 else /* fork() returns new pid to the parent process */
595 // must do before resuming signals to avoid race
610 int status;
/* parent process: child's exit status */
612 /* wait for child to exit, and store its status */
616 continue;
// try again
621 perror(
"Waiting for child process failed");
644 else /* fork returns -1 on failure */
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
int open(const char *pathname, int flags,...)
int __CPROVER_ID java::java io InputStream read
output_type narrow(input_type input)
Run-time checked narrowing cast.
int run(const std::string &what, const std::vector< std::string > &argv)
static fdt stdio_redirection(int fd, const std::string &file)
open given file to replace either stdin, stderr, stdout
std::string shell_quote(const std::string &src)
quote a string for bash and CMD
void remove_signal_catcher()
void register_child(pid_t pid)
#define UNREACHABLE
This should be used to mark dead code.
void perror(const char *s)
char * strdup(const char *str)
exprt buffer_size(const exprt &what)
std::wstring widen(const char *s)