/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2004-2021 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include using namespace mailutils; // // Stream // Stream :: Stream () { this->stm = 0; this->opened = false; reference (); } Stream :: Stream (const mu_stream_t stm) { if (stm == 0) throw Exception ("Stream::Stream", EINVAL); this->stm = stm; this->opened = false; reference (); } Stream :: Stream (Stream& s) { s.reference (); this->stm = s.stm; } Stream :: ~Stream () { if (dereference ()) { close (); if (this->stm) mu_stream_destroy (&stm); } } void Stream :: open () { int status = mu_stream_open (stm); if (status == EAGAIN) throw Stream::EAgain ("Stream::open", status); else if (status) throw Exception ("Stream::open", status); this->opened = true; } void Stream :: close () { if (this->opened) { int status = mu_stream_close (stm); if (status) throw Exception ("Stream::close", status); this->opened = false; } } void Stream :: set_waitflags (int flags) { this->wflags = flags; } void Stream :: wait () { int status = mu_stream_wait (stm, &wflags, NULL); if (status) throw Exception ("Stream::wait", status); } void Stream :: wait (int flags) { this->wflags = flags; int status = mu_stream_wait (stm, &wflags, NULL); if (status) throw Exception ("Stream::wait", status); } int Stream :: read (void* rbuf, size_t size) { int status = mu_stream_read (stm, rbuf, size, &read_count); if (status == EAGAIN) throw Stream::EAgain ("Stream::read", status); else if (status) throw Exception ("Stream::read", status); return status; } int Stream :: write (void* wbuf, size_t size) { int status = mu_stream_write (stm, wbuf, size, &write_count); if (status == EAGAIN) throw Stream::EAgain ("Stream::write", status); else if (status) throw Exception ("Stream::write", status); return status; } int Stream :: write (const std::string& wbuf, size_t size) { int status = mu_stream_write (stm, wbuf.c_str (), size, &write_count); if (status == EAGAIN) throw Stream::EAgain ("Stream::write", status); else if (status) throw Exception ("Stream::write", status); return status; } int Stream :: readline (char* rbuf, size_t size) { int status = mu_stream_readline (stm, rbuf, size, &read_count); if (status == EAGAIN) throw Stream::EAgain ("Stream::readline", status); else if (status) throw Exception ("Stream::readline", status); return status; } void Stream :: flush () { int status = mu_stream_flush (stm); if (status) throw Exception ("Stream::flush", status); } namespace mailutils { Stream& operator << (Stream& stm, const std::string& wbuf) { stm.write (wbuf, wbuf.length ()); return stm; } Stream& operator >> (Stream& stm, std::string& rbuf) { char tmp[1024]; stm.read (tmp, sizeof (tmp)); rbuf = std::string (tmp); return stm; } } // // TcpStream // TcpStream :: TcpStream (const std::string& host, int port, int flags) { int status = mu_tcp_stream_create (&stm, host.c_str (), port, flags); if (status) throw Exception ("TcpStream::TcpStream", status); } // // FileStream // FileStream :: FileStream (const std::string& filename, int flags) { int status = mu_file_stream_create (&stm, filename.c_str (), flags); if (status) throw Exception ("FileStream::FileStream", status); } // // StdioStream // StdioStream :: StdioStream (int fd, int flags) { int status = mu_stdio_stream_create (&stm, fd, flags); if (status) throw Exception ("StdioStream::StdioStream", status); } // // ProgStream /* FIXME: This must be revised using the real prog_stream interface, instead of the command_stream */ ProgStream :: ProgStream (const std::string& progname, int flags) { int status = mu_command_stream_create (&stm, progname.c_str (), flags); if (status) throw Exception ("ProgStream::ProgStream", status); } // // FilterProgStream // FilterProgStream :: FilterProgStream (const std::string& progname, Stream& input) { struct mu_prog_hints hints; struct mu_wordsplit ws; int status; if (mu_wordsplit (progname.c_str (), &ws, MU_WRDSF_DEFFLAGS)) throw Exception ("FilterProgStream::FilterProgStream", errno); hints.mu_prog_input = input.stm; status = mu_prog_stream_create (&stm, ws.ws_wordv[0], ws.ws_wordc, ws.ws_wordv, MU_PROG_HINT_INPUT, &hints, MU_STREAM_READ); mu_wordsplit_free (&ws); if (status) throw Exception ("FilterProgStream::FilterProgStream", status); this->input = new Stream (input); } FilterProgStream :: FilterProgStream (const std::string& progname, Stream* input) { FilterProgStream (progname, input); }