adbncfs  0.9.1
spawn.cpp
Go to the documentation of this file.
1 /*
2  * $Id: spawn.cpp 5 2015-12-06 18:57:22Z wejaeger $
3  *
4  * File: spawn.cpp
5  * Author: Werner Jaeger
6  *
7  * Created on November 19, 2015, 5:33 PM
8  *
9  * Copyright 2015 Werner Jaeger.
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <http://www.gnu.org/licenses/>.
23  */
24 
25 #ifndef SPAWN_CPP
26 #define SPAWN_CPP
27 
28 #include "spawn.h"
29 
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <sys/wait.h>
33 #include <stdexcept>
34 
35 using namespace std;
36 
38 {
39  if (::pipe(m_aiFd))
40  {
41  string strErr("Failed to create pipe. Errno: ");
42  strErr += to_string(errno);
43  throw runtime_error(strErr);
44  }
45 }
46 
47 const inline int Cpipe::readFd() const
48 {
49  return m_aiFd[0];
50 }
51 
52 const inline int Cpipe::writeFd() const
53 {
54  return m_aiFd[1];
55 }
56 
58 {
59  ::close(m_aiFd[0]);
60  ::close(m_aiFd[1]);
61 }
62 
64 {
65  close();
66 }
67 
87 Spawn::Spawn(const char* const argv[], bool fUseStdErr, bool fWithPath, const char* const envp[]): m_iChildPid(-1), m_pWriteBuf(NULL), m_pReadBuf(NULL), stdin(NULL), stdout(NULL), m_WritePipe(), m_ReadPipe()
88 {
89  m_iChildPid = ::fork();
90  if (m_iChildPid == -1)
91  throw runtime_error("Failed to start child process");
92 
93  if (m_iChildPid == 0)
94  {
95  // In child process
96  ::dup2(m_WritePipe.readFd(), STDIN_FILENO);
97 
98  if (fUseStdErr)
99  ::dup2(m_ReadPipe.writeFd(), STDERR_FILENO);
100  else
101  ::dup2(m_ReadPipe.writeFd(), STDOUT_FILENO);
102 
103  m_WritePipe.close();
104  m_ReadPipe.close();
105 
106  int iRes;
107  if (fWithPath)
108  {
109  if (envp != 0)
110  iRes = ::execvpe(argv[0], const_cast<char* const*>(argv), const_cast<char* const*>(envp));
111  else
112  iRes = ::execvp(argv[0], const_cast<char* const*>(argv));
113  }
114  else
115  {
116  if (envp != 0)
117  iRes = ::execve(argv[0], const_cast<char* const*>(argv), const_cast<char* const*>(envp));
118  else
119  iRes = ::execv(argv[0], const_cast<char* const*>(argv));
120  }
121 
122  if (iRes == -1)
123  {
124  if (fUseStdErr)
125  cout << "Error: Failed to launch program \"" << argv[0] << "\" Error: " << to_string(errno) << endl;
126  else
127  cerr << "Error: Failed to launch program \"" << argv[0] << "\" Error: " << to_string(errno) << endl;
128 
129  ::exit(errno);
130  }
131  }
132  else
133  {
134  ::close(m_WritePipe.readFd());
135  ::close(m_ReadPipe.writeFd());
136  m_pWriteBuf = new __gnu_cxx::stdio_filebuf<char>(m_WritePipe.writeFd(), ios::out);
137  m_pReadBuf = new __gnu_cxx::stdio_filebuf<char>(m_ReadPipe.readFd(), ios::in);
138  stdin.rdbuf(m_pWriteBuf);
139  stdout.rdbuf(m_pReadBuf);
140  }
141 }
142 
144 {
145  if (m_pWriteBuf)
146  delete m_pWriteBuf;
147 
148  if (m_pReadBuf)
149  delete m_pReadBuf;
150 }
151 
153 {
154  m_pWriteBuf->close();
155 }
156 
173 {
174  int iStatus;
175 
176  do
177  {
178  pid_t iTerminatedPid(::waitpid(m_iChildPid, &iStatus, WUNTRACED | WCONTINUED));
179  if (iTerminatedPid == -1)
180  {
181  iStatus = EXIT_FAILURE;
182  break;
183  }
184  } while (!WIFEXITED(iStatus) && !WIFSIGNALED(iStatus));
185 
186  return(iStatus);
187 }
188 
189 #endif /* SPAWN_CPP */
Cpipe m_WritePipe
Definition: spawn.h:100
Cpipe m_ReadPipe
Definition: spawn.h:101
virtual ~Spawn()
Definition: spawn.cpp:143
__gnu_cxx::stdio_filebuf< char > * m_pReadBuf
Definition: spawn.h:97
int wait()
Wait until child process has terminated.
Definition: spawn.cpp:172
std::ostream stdin
Definition: spawn.h:98
const int writeFd() const
Definition: spawn.cpp:52
void sendEof()
Definition: spawn.cpp:152
Spawn(const char *const argv[], bool fUseStdErr=false, bool fWithPath=false, const char *const envp[]=NULL)
Spawns a child process.
Definition: spawn.cpp:87
const int readFd() const
Definition: spawn.cpp:47
int m_iChildPid
Definition: spawn.h:95
std::istream stdout
Definition: spawn.h:99
void close()
Definition: spawn.cpp:57
Cpipe()
Definition: spawn.cpp:37
virtual ~Cpipe()
Definition: spawn.cpp:63
__gnu_cxx::stdio_filebuf< char > * m_pWriteBuf
Definition: spawn.h:96