]> git.tdb.fi Git - libs/core.git/blob - source/core/unix/process.cpp
Add a Process class for running and interfacing with other programs
[libs/core.git] / source / core / unix / process.cpp
1 #include <unistd.h>
2 #include <sys/wait.h>
3 #include <signal.h>
4 #include <msp/core/systemerror.h>
5 #include <msp/fs/dir.h>
6 #include <msp/io/console.h>
7 #include "process.h"
8 #include "process_private.h"
9
10 using namespace std;
11
12 namespace Msp {
13
14 Process::~Process()
15 { }
16
17 void Process::platform_get_self_info(Private &priv)
18 {
19         priv.info.pid = getpid();
20 }
21
22 void Process::execute(const string &command, bool path_search, const Arguments &args)
23 {
24         pid_t pid = 0;
25         if(this!=_self)
26                 pid = fork();
27
28         if(pid==-1)
29                 throw system_error("fork");
30         else if(pid==0)
31         {
32                 try
33                 {
34                         vector<const char *> argv(args.size()+2);
35                         argv[0] = command.c_str();
36                         for(unsigned i=0; i<args.size(); ++i)
37                                 argv[i+1] = args[i].c_str();
38                         argv[args.size()+1] = 0;
39
40                         if(redirect)
41                         {
42                                 if(cin)
43                                         IO::cin.redirect(*cin);
44                                 if(cout)
45                                         IO::cout.redirect(*cout);
46                                 if(cerr)
47                                         IO::cerr.redirect(*cerr);
48                         }
49
50                         if(!work_dir.empty())
51                                 FS::chdir(work_dir);
52
53                         if(path_search)
54                                 execvp(command.c_str(), const_cast<char *const *>(&argv[0]));
55                         else
56                                 execv(command.c_str(), const_cast<char *const *>(&argv[0]));
57                 }
58                 catch(...)
59                 { }
60                 _exit(255);
61         }
62         else
63         {
64                 priv->info.pid = pid;
65                 running = true;
66         }
67 }
68
69 bool Process::wait(bool block)
70 {
71         if(!running)
72                 throw logic_error("not running");
73
74         int status;
75         int pid = waitpid(priv->info.pid, &status, (block ? 0 : WNOHANG));
76         if(pid==-1)
77                 throw system_error("waitpid");
78
79         if(pid)
80         {
81                 finished = true;
82                 running = false;
83                 if(WIFEXITED(status))
84                         exit_code = WEXITSTATUS(status);
85                 else if(WIFSIGNALED(status))
86                         exit_code = 0x100|WTERMSIG(status);
87         }
88
89         return finished;
90 }
91
92 void Process::terminate()
93 {
94         ::kill(priv->info.pid, SIGTERM);
95 }
96
97 void Process::kill()
98 {
99         ::kill(priv->info.pid, SIGKILL);
100 }
101
102 void Process::interrupt()
103 {
104         ::kill(priv->info.pid, SIGINT);
105 }
106
107
108 Process::Private::Private()
109 {
110         info.pid = 0;
111 }
112
113 } // namespace Msp