change permissions before fsync()
[libi2ncommon] / src / pipestream.cpp
CommitLineData
7e606af5
GE
1 /*
2The software in this package is distributed under the GNU General
3Public License version 2 (with a special exception described below).
4
5A copy of GNU General Public License (GPL) is included in this distribution,
6in the file COPYING.GPL.
7
8As a special exception, if other files instantiate templates or use macros
9or inline functions from this file, or you compile this file and link it
10with other works to produce a work based on this file, this file
11does not by itself cause the resulting work to be covered
12by the GNU General Public License.
13
14However the source code for this file must still be made available
15in accordance with section (3) of the GNU General Public License.
16
17This exception does not invalidate any other reasons why a work based
18on this file might be covered by the GNU General Public License.
19*/
20/***************************************************************************
21 inpipestream.cpp - C++ streambuffer wrapper
22 -------------------
23 begin : Thu Dec 27 2001
24 copyright : (C) 2001 by Intra2net AG
25 ***************************************************************************/
26
27#include <stdio.h>
f8f119bf 28#include <sys/wait.h>
7e606af5
GE
29
30#include <string>
31#include <streambuf>
32#include <istream>
33#include <ostream>
34#include <cstdio>
35
36#include "exception.hxx"
37#include "pipestream.hxx"
38
f8f119bf
GE
39/** @brief runs command and returns it's output as string
40 * @param command the full command with all parameters
41 * @param rescode struct containing the return code, if the program exited normally and so on
42 * @returns the output (stdout) of the called program
43 */
44std::string capture_exec(const std::string& command, ExecResult &rescode)
45{
46 std::string output;
47
1d7539d5 48 bool exit_set = false;
f8f119bf
GE
49 int exit_status_waitpid;
50
51 // set the results to false until we are sure we have proper values
52 rescode.normal_exit = false;
53 rescode.terminated_by_signal = false;
54
55 try
56 {
57 {
58 inpipestream ips(command);
59
60 ips.store_exit_status(&exit_set, &exit_status_waitpid);
61
62 char buffer[2048];
63 while (ips.good())
64 {
65 ips.read(buffer, sizeof(buffer));
66 output.append(buffer, ips.gcount());
67 }
68 }
69
70 // exit_status_waitpid only valid after destruction of the inpipestream
71
72 if (exit_set)
73 {
74 rescode.normal_exit = WIFEXITED(exit_status_waitpid);
75 if (rescode.normal_exit)
76 rescode.return_code = WEXITSTATUS(exit_status_waitpid);
77
78 rescode.terminated_by_signal = WIFSIGNALED(exit_status_waitpid);
79 if (rescode.terminated_by_signal)
80 rescode.signal = WTERMSIG(exit_status_waitpid);
81 }
82 }
83 catch (pipestream_error &e)
84 {
85 rescode.error_message = e.what();
86 }
87
88 return output;
89}
90
7e606af5
GE
91inpipebuf::inpipebuf(const std::string& command)
92{
93 status_set = NULL;
94 exit_status = NULL;
95
96 pipe = popen (command.c_str(), "r");
97 if (pipe == NULL)
98 throw EXCEPTION (pipestream_error, "can't open program or permission denied");
99
100 // force underflow
101 setg (&buffer, &buffer, &buffer);
102}
103
104inpipebuf::~inpipebuf()
105{
106 if (pipe != NULL) {
107 int pclose_exit = pclose (pipe);
108
d00589a0
GE
109 if (exit_status && pclose_exit != -1)
110 {
111 if (status_set)
112 *status_set = true;
7e606af5
GE
113 *exit_status = pclose_exit;
114 }
115
116 pipe = NULL;
117 }
118}
119
120/** note: exit status only available after destruction */
121void inpipebuf::store_exit_status(bool *_status_set, int *_exit_status)
122{
123 status_set = _status_set;
124 exit_status = _exit_status;
125}
126
127inpipebuf::int_type inpipebuf::underflow()
128{
129 if (gptr() < egptr())
130 return traits_type::to_int_type(*gptr());
131
132 buffer = fgetc (pipe);
133 if (feof (pipe))
134 {
135 // ERROR or EOF
136 return EOF;
137 }
138
139 setg (&buffer, &buffer, &buffer+sizeof(char));
140
141 return traits_type::to_int_type(*gptr());
142}
143
7e606af5
GE
144outpipebuf::outpipebuf(const std::string& command)
145{
146 status_set = NULL;
147 exit_status = NULL;
148
149 pipe = popen (command.c_str(), "w");
150 if (pipe == NULL)
151 throw EXCEPTION (pipestream_error, "can't open program or permission denied");
152}
153
154outpipebuf::~outpipebuf()
155{
156 if (pipe != NULL) {
157 int pclose_exit = pclose (pipe);
158
d00589a0
GE
159 if (exit_status && pclose_exit != -1)
160 {
161 if (status_set)
162 *status_set = true;
7e606af5
GE
163 *exit_status = pclose_exit;
164 }
165
166 pipe = NULL;
167 }
168}
169
170/** note: exit status only available after destruction */
171void outpipebuf::store_exit_status(bool *_status_set, int *_exit_status)
172{
173 status_set = _status_set;
174 exit_status = _exit_status;
175}
176
177outpipebuf::int_type outpipebuf::overflow(int_type c)
178{
179 if (c != EOF)
180 {
181 if (fputc(c,pipe)==EOF)
182 return EOF;
183 }
184 return c;
185}
186
187std::streamsize outpipebuf::xsputn(const char* s, std::streamsize num)
188{
189 return fwrite(s,num,1,pipe);
190}