bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
a2583397219ebbb877fcf84107f0ca7f56362760Timo Sirainenstatic int o_stream_dot_finish(struct ostream_private *stream)
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch struct dot_ostream *dstream = (struct dot_ostream *)stream;
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen if (o_stream_get_buffer_avail_size(stream->parent) < 5) {
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen /* make space for the dot line */
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen if ((ret = o_stream_flush(stream->parent)) <= 0) {
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen ret = o_stream_send(stream->parent, ".\r\n", 3);
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen ret = o_stream_send(stream->parent, "\r\n.\r\n", 5);
a2583397219ebbb877fcf84107f0ca7f56362760Timo Siraineno_stream_dot_flush(struct ostream_private *stream)
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Siraineno_stream_dot_close(struct iostream_private *stream, bool close_parent)
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen struct dot_ostream *dstream = (struct dot_ostream *)stream;
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Boscho_stream_dot_sendv(struct ostream_private *stream,
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch const struct const_iovec *iov, unsigned int iov_count)
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch struct dot_ostream *dstream = (struct dot_ostream *)stream;
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen i_assert(dstream->state != STREAM_STATE_DONE);
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch if ((ret=o_stream_flush(stream->parent)) <= 0) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* error / we still couldn't flush existing data to
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch parent stream. */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* check for dots */
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen max_bytes = o_stream_get_buffer_avail_size(stream->parent);
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Sirainen i_assert(max_bytes > 0); /* FIXME: not supported currently */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch for (i = 0; i < iov_count && max_bytes > 0; i++) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch const char *data = iov[i].iov_base, *p, *pend;
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch for (; p < pend && (size_t)(p-data) < (max_bytes-2); p++) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch switch (*p) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* add missing CR */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch switch (*p) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* got CRLF, or the first line */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch switch (*p) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* add missing CR */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* add dot */
8409959d66804dc963bc6fcdcc9a01da0d56a978Timo Sirainen /* fall through */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* forward chunk to new iovec */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* insert byte (substitute one with pair) */
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch iovn.iov_base = (add == '\r' ? "\r\n" : "..");
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch } else if ((ret=o_stream_sendv(stream->parent, iov_new, count)) <= 0) {
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch /* all must be sent */
83773f7eb5e12e68f5efee7278bdab35d2ee84c0Timo Siraineno_stream_create_dot(struct ostream *output, bool force_extra_crlf)
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch dstream->ostream.iostream.close = o_stream_dot_close;
836e690c0e2d7494b8c0a6f4984dd13248841f2fStephan Bosch dstream->ostream.max_buffer_size = output->real_stream->max_buffer_size;
6519bf9a290ff036ede005ac66b1a339e5931c26Timo Sirainen (void)o_stream_create(&dstream->ostream, output, o_stream_get_fd(output));
6519bf9a290ff036ede005ac66b1a339e5931c26Timo Sirainen /* ostream-dot is always used inside another ostream that shouldn't
6519bf9a290ff036ede005ac66b1a339e5931c26Timo Sirainen get finished when the "." line is written. Disable it here so all
6519bf9a290ff036ede005ac66b1a339e5931c26Timo Sirainen of the callers don't have to set this. */