split pipestream.hxx into .hxx and .cpp
[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>
28
29#include <string>
30#include <streambuf>
31#include <istream>
32#include <ostream>
33#include <cstdio>
34
35#include "exception.hxx"
36#include "pipestream.hxx"
37
38inpipebuf::inpipebuf(const std::string& command)
39{
40 status_set = NULL;
41 exit_status = NULL;
42
43 pipe = popen (command.c_str(), "r");
44 if (pipe == NULL)
45 throw EXCEPTION (pipestream_error, "can't open program or permission denied");
46
47 // force underflow
48 setg (&buffer, &buffer, &buffer);
49}
50
51inpipebuf::~inpipebuf()
52{
53 if (pipe != NULL) {
54 int pclose_exit = pclose (pipe);
55
56 if (exit_status && pclose_exit != -1) {
57 *status_set = true;
58 *exit_status = pclose_exit;
59 }
60
61 pipe = NULL;
62 }
63}
64
65/** note: exit status only available after destruction */
66void inpipebuf::store_exit_status(bool *_status_set, int *_exit_status)
67{
68 status_set = _status_set;
69 exit_status = _exit_status;
70}
71
72inpipebuf::int_type inpipebuf::underflow()
73{
74 if (gptr() < egptr())
75 return traits_type::to_int_type(*gptr());
76
77 buffer = fgetc (pipe);
78 if (feof (pipe))
79 {
80 // ERROR or EOF
81 return EOF;
82 }
83
84 setg (&buffer, &buffer, &buffer+sizeof(char));
85
86 return traits_type::to_int_type(*gptr());
87}
88
89/** @brief runs command and returns it's output as string
90 * @param command the full command with all parameters
91 * @param exit_status the full exit status, use WEXITSTATUS to get the "regular" return code
92 * @returns the output (stderr) of the called program
93 */
94std::string pipe_to_string(const std::string& command, std::string *error, int *_exit_status)
95{
96 std::string result;
97 bool exit_set;
98
99 try
100 {
101 inpipestream ips(command);
102
103 ips.store_exit_status(&exit_set, _exit_status);
104
105 char buffer[2048];
106 while (ips.good())
107 {
108 ips.read(buffer, sizeof(buffer));
109 result.append(buffer, ips.gcount());
110 }
111 }
112 catch (pipestream_error &e)
113 {
114 if (error)
115 *error=e.what();
116 return "";
117 }
118 catch(...)
119 {
120 throw;
121 }
122
123 return result;
124}
125
126outpipebuf::outpipebuf(const std::string& command)
127{
128 status_set = NULL;
129 exit_status = NULL;
130
131 pipe = popen (command.c_str(), "w");
132 if (pipe == NULL)
133 throw EXCEPTION (pipestream_error, "can't open program or permission denied");
134}
135
136outpipebuf::~outpipebuf()
137{
138 if (pipe != NULL) {
139 int pclose_exit = pclose (pipe);
140
141 if (exit_status && pclose_exit != -1) {
142 *status_set = true;
143 *exit_status = pclose_exit;
144 }
145
146 pipe = NULL;
147 }
148}
149
150/** note: exit status only available after destruction */
151void outpipebuf::store_exit_status(bool *_status_set, int *_exit_status)
152{
153 status_set = _status_set;
154 exit_status = _exit_status;
155}
156
157outpipebuf::int_type outpipebuf::overflow(int_type c)
158{
159 if (c != EOF)
160 {
161 if (fputc(c,pipe)==EOF)
162 return EOF;
163 }
164 return c;
165}
166
167std::streamsize outpipebuf::xsputn(const char* s, std::streamsize num)
168{
169 return fwrite(s,num,1,pipe);
170}