Continued ripping up the source.
[aesalon.git] / monitor / src / BidirectionalPipe.cpp
blobd20f35f41ed34f237e0642bc1c9c9bf888c2e707
1 #include <unistd.h>
2 #include <cstring>
3 #include <sys/types.h>
4 #include <sys/ptrace.h>
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <iostream>
8 #include "BidirectionalPipe.h"
9 #include "misc/Exception.h"
11 namespace Aesalon {
12 namespace Platform {
14 BidirectionalPipeException::BidirectionalPipeException(std::string message,
15 bool strerr) : Misc::Exception(Misc::StreamAsString() << message << (strerr?strerror(errno):"")) {
18 BidirectionalPipe::BidirectionalPipe(Misc::ArgumentList argument_list, bool block) : block(block) {
20 pipe(pc_pipe_fd);
21 pipe(cp_pipe_fd);
23 pid = fork();
25 if(pid == -1) throw BidirectionalPipeException("Could not fork to execute child process: ", true);
26 else if(pid == 0) {
27 close(pc_pipe_fd[1]); /* Close the write end of the pc pipe */
28 close(cp_pipe_fd[0]); /* Close the read end of the cp pipe */
30 fcntl(pc_pipe_fd[0], F_SETFL, fcntl(pc_pipe_fd[0], F_GETFL) & ~O_NONBLOCK);
31 fcntl(cp_pipe_fd[1], F_SETFL, fcntl(cp_pipe_fd[1], F_GETFL) & ~O_NONBLOCK);
33 dup2(pc_pipe_fd[0], STDIN_FILENO);
34 dup2(cp_pipe_fd[1], STDOUT_FILENO);
36 execv(argument_list.get_argument(0).c_str(), argument_list.get_as_argv());
38 throw BidirectionalPipeException("Failed to execute file: ", true);
40 close(pc_pipe_fd[0]); /* Close the read end of the pc pipe */
41 close(cp_pipe_fd[1]); /* Close the write end of the cp pipe */
43 fcntl(pc_pipe_fd[1], F_SETFL, fcntl(cp_pipe_fd[1], F_GETFL) & ~O_NONBLOCK);
44 set_blocking(block);
46 /* Pipe opened and ready to go. */
47 is_connected = true;
50 BidirectionalPipe::~BidirectionalPipe() {
51 if(is_connected) close(pc_pipe_fd[1]), close(cp_pipe_fd[0]);
52 is_connected = false;
55 std::string BidirectionalPipe::get_string() {
56 std::string data;
57 char recv;
58 int ret_value;
60 if(!is_open()) return "";
62 while((ret_value = read(cp_pipe_fd[0], &recv, sizeof(recv))) > 0) {
63 if(recv == '\n') {
64 return data;
66 data += recv;
68 /* EAGAIN on a pipe read with O_NONBLOCK set means no data waiting. */
69 if(!block && ret_value == -1 && errno == EAGAIN) {
70 return "";
72 is_connected = false;
73 return data;
76 void BidirectionalPipe::send_string(std::string data) {
77 if(is_open()) write(pc_pipe_fd[1], data.c_str(), data.length());
80 void BidirectionalPipe::set_blocking(bool new_blocking) {
81 block = new_blocking;
82 if(!block) fcntl(cp_pipe_fd[0], F_SETFL, fcntl(cp_pipe_fd[0], F_GETFL) | O_NONBLOCK);
83 else fcntl(cp_pipe_fd[0], F_SETFL, fcntl(cp_pipe_fd[0], F_GETFL) & ~O_NONBLOCK);
86 } // namespace Platform
87 } // namespace Aesalon