1 // Copyright 2022 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #ifndef COMMON_LINUX_SCOPED_PIPE_H_ 30 #define COMMON_LINUX_SCOPED_PIPE_H_ 31 32 #include <stdint.h> 33 #include <string> 34 35 namespace google_breakpad { 36 37 // Small RAII wrapper for a pipe pair. 38 // 39 // Example (both ends of pipe in same process): 40 // ScopedPipe tmp; 41 // std::string line; 42 // if (tmp.Init() && tmp.Write(bytes, bytes_len)) { 43 // tmp.CloseWriteFd(); 44 // while (tmp.ReadLine(&line)) { 45 // std::cerr << line << std::endl; 46 // } 47 // } 48 // 49 // Example (reading output from a child process): 50 // ScopedPipe tmp; 51 // if (fork()) { 52 // // Parent process, read from the read end of the pipe. 53 // std::string line; 54 // while (tmp.ReadLine(line)) { 55 // // Process output... 56 // } 57 // // Close read pipe once done processing the output that we wanted, this 58 // // should ensure that the child process exits even if we didn't read all 59 // // of the output. 60 // tmp.CloseReadFd(); 61 // // Parent process should handle waiting for child to exit here... 62 // } else { 63 // // Child process, close the read fd and dup the write fd before exec'ing. 64 // tmp.CloseReadFd(); 65 // tmp.Dup2WriteFd(STDOUT_FILENO); 66 // tmp.Dup2WriteFd(STDERR_FILENO); 67 // execl("some-command", "some-arguments"); 68 // } 69 class ScopedPipe { 70 public: 71 ScopedPipe(); 72 ~ScopedPipe(); 73 74 // Creates the pipe pair - returns false on error. 75 bool Init(); 76 77 // Close the read pipe. This only needs to be used when the read pipe needs to 78 // be closed earlier. 79 void CloseReadFd(); 80 81 // Close the write pipe. This only needs to be used when the write pipe needs 82 // to be closed earlier. 83 void CloseWriteFd(); 84 85 // Reads characters until newline or end of pipe. On read failure this will 86 // close the read pipe, but continue to return true and read buffered lines 87 // until the internal buffering is exhausted. This will block if there is no 88 // data available on the read pipe. 89 bool ReadLine(std::string& line); 90 91 // Writes bytes to the write end of the pipe, returns false and closes write 92 // pipe on failure. 93 bool WriteForTesting(const void* bytes, size_t bytes_len); 94 95 // Calls the dup2 system call to replace any existing open file descriptor 96 // with number new_fd with a copy of the current write end file descriptor 97 // for the pipe. 98 int Dup2WriteFd(int new_fd) const; 99 100 private: GetReadFd()101 int GetReadFd() const { 102 return fds_[0]; 103 } 104 GetWriteFd()105 int GetWriteFd() const { 106 return fds_[1]; 107 } 108 109 int fds_[2]; 110 std::string read_buffer_; 111 }; 112 113 } // namespace google_breakpad 114 115 #endif // COMMON_LINUX_SCOPED_PIPE_H_ 116