Line data Source code
1 : // Snap Websites Server -- C++ object to safely handle a pipe
2 : // Copyright (c) 2013-2019 Made to Order Software Corp. All Rights Reserved
3 : //
4 : // This program is free software; you can redistribute it and/or modify
5 : // it under the terms of the GNU General Public License as published by
6 : // the Free Software Foundation; either version 2 of the License, or
7 : // (at your option) any later version.
8 : //
9 : // This program is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : // GNU General Public License for more details.
13 : //
14 : // You should have received a copy of the GNU General Public License
15 : // along with this program; if not, write to the Free Software
16 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 :
18 :
19 : // self
20 : //
21 : #include "snapwebsites/snap_pipe.h"
22 :
23 :
24 : // snapwebsites lib
25 : //
26 : #include "snapwebsites/qstring_stream.h"
27 :
28 :
29 : // last include
30 : //
31 : #include <snapdev/poison.h>
32 :
33 :
34 :
35 :
36 :
37 : namespace snap
38 : {
39 :
40 :
41 :
42 0 : snap_pipe::snap_pipe(QString const & command, mode_t mode)
43 : : f_command(command)
44 : , f_mode(mode)
45 0 : , f_file(popen(f_command.toUtf8().data(), mode_t::PIPE_MODE_IN == mode ? "w" : "r"))
46 : {
47 0 : if(f_file == nullptr)
48 : {
49 0 : throw snap_pipe_exception_cannot_open(QString("popen(\"%1\", \"%2\") failed to start command")
50 0 : .arg(f_command)
51 0 : .arg(mode == mode_t::PIPE_MODE_IN ? "w" : "r"));
52 : }
53 0 : }
54 :
55 :
56 0 : snap_pipe::~snap_pipe()
57 : {
58 : // make sure f_file gets closed
59 : //
60 0 : close_pipe();
61 0 : }
62 :
63 :
64 0 : QString const& snap_pipe::get_command() const
65 : {
66 0 : return f_command;
67 : }
68 :
69 :
70 0 : snap_pipe::mode_t snap_pipe::get_mode() const
71 : {
72 0 : return f_mode;
73 : }
74 :
75 :
76 0 : int snap_pipe::close_pipe()
77 : {
78 0 : int r(-1);
79 0 : if(f_file != nullptr)
80 : {
81 0 : if(ferror(f_file))
82 : {
83 : // must return -1 on error
84 0 : pclose(f_file);
85 : }
86 : else
87 : {
88 0 : r = pclose(f_file);
89 : }
90 0 : f_file = nullptr;
91 : }
92 0 : return r;
93 : }
94 :
95 :
96 0 : std::ostream::int_type snap_pipe::overflow(int_type c)
97 : {
98 : #ifdef DEBUG
99 0 : if(mode_t::PIPE_MODE_IN != f_mode)
100 : {
101 0 : throw snap_pipe_exception_cannot_write("pipe opened in read mode, cannot write to it");
102 : }
103 : #endif
104 :
105 0 : if(f_file == nullptr)
106 : {
107 0 : throw snap_pipe_exception_no_file("file was closed");
108 : }
109 :
110 0 : if(c != EOF)
111 : {
112 0 : if(fputc(static_cast<int>(c), f_file) == EOF)
113 : {
114 0 : return EOF;
115 : }
116 : }
117 0 : return c;
118 : }
119 :
120 :
121 0 : std::ostream::int_type snap_pipe::underflow()
122 : {
123 : #ifdef DEBUG
124 0 : if(mode_t::PIPE_MODE_OUT != f_mode)
125 : {
126 0 : throw snap_pipe_exception_cannot_read("pipe opened in write mode, cannot read from it");
127 : }
128 : #endif
129 :
130 0 : if(f_file == nullptr)
131 : {
132 0 : throw snap_pipe_exception_no_file("file was closed");
133 : }
134 :
135 0 : int c(fgetc(f_file));
136 0 : if(c < 0 || c > 255)
137 : {
138 0 : throw snap_pipe_exception_cannot_read(QString("snap_pipe::underflow(): fgetc() returned an error (%1)").arg(c));
139 : }
140 :
141 0 : return static_cast<std::ostream::int_type>(c);
142 : }
143 :
144 :
145 : //int snap_pipe::write(char const *buf, size_t size)
146 : //{
147 : // return fwrite(buf, 1, size, f_file);
148 : //}
149 : //
150 : //
151 : //int snap_pipe::read(char *buf, size_t size)
152 : //{
153 : // return fread(buf, 1, size, f_file);
154 : //}
155 :
156 :
157 6 : } // namespace snap
158 :
159 : // vim: ts=4 sw=4 et
|