]> git.tdb.fi Git - builder.git/blobdiff - source/externaltask.cpp
Big rewrite for a more tool-centric approach
[builder.git] / source / externaltask.cpp
diff --git a/source/externaltask.cpp b/source/externaltask.cpp
new file mode 100644 (file)
index 0000000..2471666
--- /dev/null
@@ -0,0 +1,58 @@
+#include <cstdlib>
+#include <sys/wait.h>
+#include <msp/fs/dir.h>
+#include <msp/io/print.h>
+#include "externaltask.h"
+
+using namespace std;
+using namespace Msp;
+
+ExternalTask::ExternalTask(const vector<string> &argv, const FS::Path &work_dir):
+       pid(-1),
+       exit_code(-1)
+{
+       if((pid = fork()))
+       {
+               if(pid==-1)
+                       exit_code = 1;
+               else
+                       exit_code = 0;
+       }
+       else
+       {
+               vector<const char *> cargv(argv.size()+1);
+               for(unsigned i=0; i<argv.size(); ++i)
+                       cargv[i] = argv[i].c_str();
+               cargv.back() = 0;
+
+               if(!work_dir.empty())
+                       FS::chdir(work_dir);
+               execvp(cargv.front(), const_cast<char *const *>(&cargv.front()));
+               IO::print("Couldn't execute %s\n", argv.front());
+               exit(1);
+       }
+}
+
+Task::Status ExternalTask::check()
+{
+       if(pid>0)
+       {
+               int status;
+               if(waitpid(pid, &status, WNOHANG)==pid)
+               {
+                       if(WIFEXITED(status))
+                               exit_code = WEXITSTATUS(status);
+                       else if(WIFSIGNALED(status))
+                               exit_code = 256+WTERMSIG(status);
+                       else
+                               exit_code = 1025;
+                       pid = 0;
+
+                       signal_finished.emit(!exit_code);
+               }
+               else
+                       return RUNNING;
+       }
+
+       return exit_code ? ERROR : SUCCESS;
+}