]> git.tdb.fi Git - builder.git/blob - source/externaltask.cpp
Big rewrite for a more tool-centric approach
[builder.git] / source / externaltask.cpp
1 #include <cstdlib>
2 #include <sys/wait.h>
3 #include <msp/fs/dir.h>
4 #include <msp/io/print.h>
5 #include "externaltask.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 ExternalTask::ExternalTask(const vector<string> &argv, const FS::Path &work_dir):
11         pid(-1),
12         exit_code(-1)
13 {
14         if((pid = fork()))
15         {
16                 if(pid==-1)
17                         exit_code = 1;
18                 else
19                         exit_code = 0;
20         }
21         else
22         {
23                 vector<const char *> cargv(argv.size()+1);
24                 for(unsigned i=0; i<argv.size(); ++i)
25                         cargv[i] = argv[i].c_str();
26                 cargv.back() = 0;
27
28                 if(!work_dir.empty())
29                         FS::chdir(work_dir);
30                 execvp(cargv.front(), const_cast<char *const *>(&cargv.front()));
31                 IO::print("Couldn't execute %s\n", argv.front());
32                 exit(1);
33         }
34 }
35
36 Task::Status ExternalTask::check()
37 {
38         if(pid>0)
39         {
40                 int status;
41                 if(waitpid(pid, &status, WNOHANG)==pid)
42                 {
43                         if(WIFEXITED(status))
44                                 exit_code = WEXITSTATUS(status);
45                         else if(WIFSIGNALED(status))
46                                 exit_code = 256+WTERMSIG(status);
47                         else
48                                 exit_code = 1025;
49                         pid = 0;
50
51                         signal_finished.emit(!exit_code);
52                 }
53                 else
54                         return RUNNING;
55         }
56
57         return exit_code ? ERROR : SUCCESS;
58 }