Line data Source code
1 : // Copyright (c) 2013-2024 Made to Order Software Corp. All Rights Reserved 2 : // 3 : // https://snapwebsites.org/project/eventdispatcher 4 : // contact@m2osw.com 5 : // 6 : // This program is free software; you can redistribute it and/or modify 7 : // it under the terms of the GNU General Public License as published by 8 : // the Free Software Foundation; either version 2 of the License, or 9 : // (at your option) any later version. 10 : // 11 : // This program is distributed in the hope that it will be useful, 12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 : // GNU General Public License for more details. 15 : // 16 : // You should have received a copy of the GNU General Public License along 17 : // with this program; if not, write to the Free Software Foundation, Inc., 18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 : 20 : // self 21 : // 22 : #include <cppprocess/io_data_pipe.h> 23 : 24 : 25 : // last include 26 : // 27 : #include <snapdev/poison.h> 28 : 29 : 30 : 31 : namespace cppprocess 32 : { 33 : 34 : 35 : 36 : /** \brief Initialize the IO data pipe. 37 : * 38 : * This constructor initialize the pipe as an input pipe. 39 : * 40 : * Once created, call the add_input() to add data to the pipe. 41 : */ 42 3 : io_data_pipe::io_data_pipe() 43 3 : : io_pipe(IO_FLAG_INPUT) 44 : { 45 3 : } 46 : 47 : 48 : /** \brief The input to be sent to stdin. 49 : * 50 : * Add the input data to be written to the stdin pipe. Note that the input 51 : * cannot be modified once the run() command was called unless the mode 52 : * is PROCESS_MODE_INOUT_INTERACTIVE. 53 : * 54 : * Note that in all case, calling this function multiple times adds more 55 : * data to the input. It does not erase what was added before. The thread 56 : * may eat some of the input in which case it gets removed from the internal 57 : * variable. 58 : * 59 : * \note 60 : * The function is safe and adding new input from the output thread 61 : * (which happens in interactive mode) is protected. 62 : * 63 : * \param[in] input The input of the process (stdin). 64 : * 65 : * \sa add_input(buffer_t const & input) 66 : */ 67 3 : void io_data_pipe::add_input(std::string const & input) 68 : { 69 : // this is additive! 70 : // 71 3 : add_input(buffer_t(input.begin(), input.end())); 72 3 : } 73 : 74 : 75 : /** \brief Binary data to be sent to stdin. 76 : * 77 : * When the input data is binary, use the QByteArray instead of a std::string 78 : * so you are sure it gets properly added. 79 : * 80 : * Calling this function multiple times appends the new data to the 81 : * existing data. 82 : * 83 : * Please, see the other set_input() function for additional information. 84 : * 85 : * \note 86 : * When sending a std::string, remember that these are converted to UTF-8 87 : * which is not compatible with purely binary data (i.e. UTF-8, for example, 88 : * does not allow for 0xFE and 0xFF.) 89 : * 90 : * \param[in] input The input of the process (stdin). 91 : * 92 : * \sa add_input(std::string const & input) 93 : */ 94 3 : void io_data_pipe::add_input(buffer_t const & input) 95 : { 96 : // this is additive! 97 : // 98 3 : f_input.insert(f_input.end(), input.begin(), input.end()); 99 3 : } 100 : 101 : 102 : /** \brief Retrieve a copy of the input buffer as a string. 103 : * 104 : * This function returns the contents of the input buffer as a string. 105 : * 106 : * \return A copy of the input. 107 : * 108 : * \sa get_binary_input() 109 : */ 110 2 : std::string io_data_pipe::get_input(bool reset) const 111 : { 112 4 : std::string input(reinterpret_cast<char const *>(f_input.data()), f_input.size()); 113 2 : if(reset) 114 : { 115 0 : const_cast<io_data_pipe *>(this)->f_input.clear(); 116 : } 117 2 : return input; 118 : } 119 : 120 : 121 : /** \brief Retrieve a copy of the input buffer. 122 : * 123 : * This function returns the contents of the input buffer. In most cases, 124 : * you'll never need this function (you should know what you add to your 125 : * command input). 126 : * 127 : * \return A copy of the input. 128 : * 129 : * \sa get_input() 130 : */ 131 2 : buffer_t io_data_pipe::get_binary_input(bool reset) const 132 : { 133 2 : buffer_t const input(f_input); 134 2 : if(reset) 135 : { 136 0 : const_cast<io_data_pipe *>(this)->f_input.clear(); 137 : } 138 2 : return input; 139 : } 140 : 141 : 142 : /** \brief Check whether the pipe is a writer or not. 143 : * 144 : * The pipe is a writer as long as it includes input data. Once the pipe 145 : * is empty, the done function will be called (after that happens, you 146 : * can't add data anymore). 147 : * 148 : * \return true until all the input data was sent to the process. 149 : */ 150 9 : bool io_data_pipe::is_writer() const 151 : { 152 9 : return f_pos < f_input.size(); 153 : } 154 : 155 : 156 : /** \brief Send some data to the process. 157 : * 158 : * This function writes the input data to the input pipe of the process. 159 : * The function writes as much data as posssible (i.e. as large as the 160 : * FIFO buffer supports) then returns. 161 : * 162 : * The function will be called as long as data can be pushed to the FIFO. 163 : * The communicator will know once there is more space available so this 164 : * function can write to the FIFO. 165 : */ 166 3 : void io_data_pipe::process_write() 167 : { 168 3 : std::size_t const size(f_input.size() - f_pos); 169 3 : if(size > 0) 170 : { 171 3 : ssize_t const r(write(f_input.data() + f_pos, size)); 172 3 : if(r > 0) 173 : { 174 3 : f_pos += r; 175 : 176 3 : if(f_pos >= f_input.size()) 177 : { 178 3 : process_done(done_reason_t::DONE_REASON_EOF); 179 : } 180 : } 181 : } 182 3 : } 183 : 184 : 185 : 186 : } // namespace cppprocess 187 : // vim: ts=4 sw=4 et