30 #include <unistd.h> |
30 #include <unistd.h> |
31 #include <sys/wait.h> |
31 #include <sys/wait.h> |
32 |
32 |
33 using namespace fm; |
33 using namespace fm; |
34 |
34 |
35 process::process(std::string path): m_path(std::move(path)) { |
35 void process::setbin(std::string path) { |
|
36 m_path = std::move(path); |
36 } |
37 } |
37 |
38 |
38 bool process::exec(std::vector<std::string> args) { |
39 void process::chdir(std::string path) { |
|
40 m_dir = std::move(path); |
|
41 } |
|
42 |
|
43 int process::exec(std::vector<std::string> args, bool capture) { |
|
44 m_output.clear(); |
|
45 |
39 // fd-pair for the pipe |
46 // fd-pair for the pipe |
40 int pipefd[2]; |
47 int pipefd[2]; |
41 |
48 |
42 if (pipe(pipefd)) { |
49 if (pipe(pipefd)) { |
43 perror("pipe"); |
50 perror("pipe"); |
44 return false; |
51 return -1; |
45 } |
52 } |
46 |
53 |
47 pid_t pid = fork(); |
54 pid_t pid = fork(); |
48 if (pid == 0) { |
55 if (pid == 0) { |
49 // connect the pipe and close the end we don't use |
56 // connect the pipe and close the end we don't use |
66 argv[++i] = arg.data(); |
73 argv[++i] = arg.data(); |
67 } |
74 } |
68 argv[args.size() + 1] = nullptr; |
75 argv[args.size() + 1] = nullptr; |
69 |
76 |
70 // execute the child program |
77 // execute the child program |
|
78 if (::chdir(m_dir.c_str())) { |
|
79 perror("chdir"); |
|
80 exit(EXIT_FAILURE); |
|
81 } |
71 if (execv(m_path.c_str(), argv)) { |
82 if (execv(m_path.c_str(), argv)) { |
72 perror("execl"); |
83 perror("execl"); |
73 exit(EXIT_FAILURE); |
84 exit(EXIT_FAILURE); |
74 } |
85 } |
75 return true; // unreachable, but the compiler doesn't know that |
86 return 0; // unreachable, but the compiler doesn't know that |
76 } else if (pid > 0) { |
87 } else if (pid > 0) { |
77 // close the end of the pipe we don't use |
88 // close the end of the pipe we don't use |
78 close(pipefd[1]); |
89 close(pipefd[1]); |
79 |
90 |
80 // read all the output |
91 // read all the output |
81 char buf[64]; |
92 if (capture) { |
82 ssize_t r; |
93 char buf[64]; |
83 while ((r = read(pipefd[0], buf, sizeof(buf))) > 0) { |
94 ssize_t r; |
84 m_output.append(buf, r); |
95 while ((r = read(pipefd[0], buf, sizeof(buf))) > 0) { |
|
96 m_output.append(buf, r); |
|
97 } |
|
98 if (r < 0) { |
|
99 perror("read"); |
|
100 } |
|
101 close(pipefd[0]); |
85 } |
102 } |
86 if (r < 0) { |
|
87 perror("read"); |
|
88 } |
|
89 close(pipefd[0]); |
|
90 |
103 |
91 // wait for the process to completely finish |
104 // wait for the process to completely finish |
92 int status = -1; |
105 int status = -1; |
93 waitpid(pid, &status, 0); |
106 waitpid(pid, &status, 0); |
94 |
107 |
95 return status == 0; |
108 return status; |
96 } else { |
109 } else { |
97 perror("fork"); |
110 perror("fork"); |
98 return false; |
111 return -1; |
99 } |
112 } |
100 } |
113 } |
101 |
114 |
102 const std::string &process::output() const { |
115 const std::string &process::output() const { |
103 return m_output; |
116 return m_output; |