+ int ret;
+ struct sb_context *sbc;
+ struct iovec iov[2];
+ struct sb_buffer sbb = SBB_INIT(band, buf, numbytes);
+ sb_transformation trafo = band < SBD_PROCEED? NULL : sc_trafo;
+
+ sbc = sb_new_send(&sbb, dont_free, trafo, scc->send);
+ do {
+ ret = sb_get_send_buffers(sbc, iov);
+ ret = xwritev(scc->fd, iov, ret);
+ if (ret < 0)
+ goto fail;
+ } while (sb_sent(sbc, ret) == false);
+ return 1;
+fail:
+ sb_free(sbc);
+ return ret;
+}
+
+/**
+ * Create a variable sized buffer and send it as a sideband packet.
+ *
+ * \param scc Passed to \ref send_sb.
+ * \param band See \ref send_sb.
+ * \param fmt The format string.
+ *
+ * \return The return value of the underlying call to \ref send_sb.
+ */
+__printf_3_4 int send_sb_va(struct stream_cipher_context *scc, int band,
+ const char *fmt, ...)
+{
+ va_list ap;
+ char *msg;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = xvasprintf(&msg, fmt, ap);
+ va_end(ap);
+ return send_sb(scc, msg, ret, band, false);
+}
+
+/**
+ * Send an error message to a client.
+ *
+ * \param cc Client info.
+ * \param err The (positive) error code.
+ *
+ * \return The return value of the underlying call to send_sb_va().
+ */
+int send_strerror(struct command_context *cc, int err)
+{
+ return cc->use_sideband?
+ send_sb_va(&cc->scc, SBD_ERROR_LOG, "%s\n", para_strerror(err))
+ :
+ sc_send_va_buffer(&cc->scc, "%s\n", para_strerror(err));
+}
+
+/**
+ * Send a sideband packet through a blocking file descriptor.
+ *
+ * \param scc fd and crypto keys.
+ * \param expected_band The expected band designator.
+ * \param max_size Passed to \ref sb_new_recv().
+ * \param result Body of the sideband packet is returned here.
+ *
+ * If \a expected_band is not \p SBD_ANY, the band designator of the received
+ * sideband packet is compared to \a expected_band and a mismatch is considered
+ * an error.
+ *
+ * \return Standard.
+ */
+int recv_sb(struct stream_cipher_context *scc,
+ enum sb_designator expected_band,
+ size_t max_size, struct iovec *result)
+{
+ int ret;
+ struct sb_context *sbc;
+ struct iovec iov;
+ struct sb_buffer sbb;
+ sb_transformation trafo;
+
+ trafo = expected_band != SBD_ANY && expected_band < SBD_PROCEED?
+ NULL : sc_trafo;
+ sbc = sb_new_recv(max_size, trafo, scc->recv);
+ for (;;) {
+ sb_get_recv_buffer(sbc, &iov);
+ ret = recv_bin_buffer(scc->fd, iov.iov_base, iov.iov_len);
+ if (ret == 0)
+ ret = -E_EOF;
+ if (ret < 0)
+ goto fail;
+ ret = sb_received(sbc, ret, &sbb);
+ if (ret < 0)
+ goto fail;
+ if (ret > 0)
+ break;
+ }
+ ret = -E_BAD_BAND;
+ if (expected_band != SBD_ANY && sbb.band != expected_band)
+ goto fail;
+ *result = sbb.iov;
+ return 1;
+fail:
+ sb_free(sbc);
+ return ret;
+}
+
+static int com_sender(struct command_context *cc)
+{
+ int i, ret = 0;