cprover
run.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening
6 
7 Date: August 2012
8 
9 \*******************************************************************/
10 
11 #include "run.h"
12 
13 #include <cassert>
14 
15 #ifdef _WIN32
16 #include <process.h>
17 #else
18 
19 #include <cstring>
20 #include <unistd.h>
21 #include <cerrno>
22 #include <cstdio>
23 #include <cstdlib>
24 
25 #include <sys/wait.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <signal.h>
30 
31 #endif
32 
33 #include <util/unicode.h>
34 #include <util/signal_catcher.h>
35 
36 int run_shell(const std::string &command)
37 {
38  std::string shell="/bin/sh";
39  std::vector<std::string> argv;
40  argv.push_back(shell);
41  argv.push_back(command);
42  return run(shell, argv, "", "");
43 }
44 
45 int run(
46  const std::string &what,
47  const std::vector<std::string> &argv,
48  const std::string &std_input,
49  const std::string &std_output)
50 {
51  #ifdef _WIN32
52  // we don't support stdin/stdout redirection on Windows
53  assert(std_input.empty());
54  assert(std_output.empty());
55 
56  // unicode version of the arguments
57  std::vector<std::wstring> wargv;
58 
59  wargv.resize(argv.size());
60 
61  for(std::size_t i=0; i<argv.size(); i++)
62  wargv[i]=widen(argv[i]);
63 
64  const wchar_t **_argv=new const wchar_t * [argv.size()+1];
65 
66  for(std::size_t i=0; i<wargv.size(); i++)
67  _argv[i]=wargv[i].c_str();
68 
69  _argv[argv.size()]=NULL;
70 
71  // warning: the arguments may still need escaping
72 
73  std::wstring wide_what=widen(what);
74 
75  int status=_wspawnvp(_P_WAIT, wide_what.c_str(), _argv);
76 
77  delete[] _argv;
78 
79  return status;
80 
81  #else
82  int stdin_fd=STDIN_FILENO;
83 
84  if(!std_input.empty())
85  {
86  stdin_fd=open(std_input.c_str(), O_RDONLY);
87  if(stdin_fd==-1)
88  {
89  perror("Failed to open stdin copy");
90  return 1;
91  }
92  }
93 
94  int stdout_fd=STDOUT_FILENO;
95 
96  if(!std_output.empty())
97  {
98  stdout_fd=open(std_output.c_str(), O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
99  if(stdout_fd==-1)
100  {
101  perror("Failed to open stdout copy");
102  return 1;
103  }
104  }
105 
106  // temporarily suspend all signals
107  sigset_t new_mask, old_mask;
108  sigemptyset(&new_mask);
109  sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
110 
111  /* now create new process */
112  pid_t childpid = fork();
113 
114  if(childpid>=0) /* fork succeeded */
115  {
116  if(childpid==0) /* fork() returns 0 to the child process */
117  {
118  // resume signals
120  sigprocmask(SIG_SETMASK, &old_mask, nullptr);
121 
122  char **_argv=new char * [argv.size()+1];
123  for(std::size_t i=0; i<argv.size(); i++)
124  _argv[i]=strdup(argv[i].c_str());
125 
126  _argv[argv.size()]=nullptr;
127 
128  if(stdin_fd!=STDIN_FILENO)
129  dup2(stdin_fd, STDIN_FILENO);
130  if(stdout_fd!=STDOUT_FILENO)
131  dup2(stdout_fd, STDOUT_FILENO);
132  execvp(what.c_str(), _argv);
133 
134  /* usually no return */
135  return 1;
136  }
137  else /* fork() returns new pid to the parent process */
138  {
139  // resume signals
140  sigprocmask(SIG_SETMASK, &old_mask, nullptr);
141 
142  int status; /* parent process: child's exit status */
143 
144  /* wait for child to exit, and store its status */
145  while(waitpid(childpid, &status, 0)==-1)
146  if(errno==EINTR)
147  continue; // try again
148  else
149  {
150  perror("Waiting for child process failed");
151  if(stdin_fd!=STDIN_FILENO)
152  close(stdin_fd);
153  if(stdout_fd!=STDOUT_FILENO)
154  close(stdout_fd);
155  return 1;
156  }
157 
158  if(stdin_fd!=STDIN_FILENO)
159  close(stdin_fd);
160  if(stdout_fd!=STDOUT_FILENO)
161  close(stdout_fd);
162 
163  return WEXITSTATUS(status);
164  }
165  }
166  else /* fork returns -1 on failure */
167  {
168  // resume signals
169  sigprocmask(SIG_SETMASK, &old_mask, nullptr);
170 
171  if(stdin_fd!=STDIN_FILENO)
172  close(stdin_fd);
173  if(stdout_fd!=STDOUT_FILENO)
174  close(stdout_fd);
175 
176  return 1;
177  }
178  #endif
179 }
std::wstring widen(const char *s)
Definition: unicode.cpp:56
void remove_signal_catcher()
int run_shell(const std::string &command)
Definition: run.cpp:36
int run(const std::string &what, const std::vector< std::string > &argv, const std::string &std_input, const std::string &std_output)
Definition: run.cpp:45