+#include "cache.h"
#include "pkt-line.h"
#include "sideband.h"
* stream, aka "verbose"). A message over band #3 is a signal that
* the remote died unexpectedly. A flush() concludes the stream.
*/
-int recv_sideband(const char *me, int in_stream, int out, int err)
+
+#define PREFIX "remote: "
+
+#define ANSI_SUFFIX "\033[K"
+#define DUMB_SUFFIX " "
+
+int recv_sideband(const char *me, int in_stream, int out)
{
- char buf[7 + LARGE_PACKET_MAX + 1];
- strcpy(buf, "remote:");
- while (1) {
+ const char *suffix;
+ char buf[LARGE_PACKET_MAX + 1];
+ struct strbuf outbuf = STRBUF_INIT;
+ int retval = 0;
+
+ if (isatty(2) && !is_terminal_dumb())
+ suffix = ANSI_SUFFIX;
+ else
+ suffix = DUMB_SUFFIX;
+
+ while (!retval) {
+ const char *b, *brk;
int band, len;
- len = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX);
+ len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX, 0);
if (len == 0)
break;
if (len < 1) {
- len = sprintf(buf, "%s: protocol error: no band designator\n", me);
- safe_write(err, buf, len);
- return SIDEBAND_PROTOCOL_ERROR;
+ strbuf_addf(&outbuf,
+ "%s%s: protocol error: no band designator",
+ outbuf.len ? "\n" : "", me);
+ retval = SIDEBAND_PROTOCOL_ERROR;
+ break;
}
- band = buf[7] & 0xff;
+ band = buf[0] & 0xff;
+ buf[len] = '\0';
len--;
switch (band) {
case 3:
- buf[7] = ' ';
- buf[8+len] = '\n';
- safe_write(err, buf, 8+len+1);
- return SIDEBAND_REMOTE_ERROR;
+ strbuf_addf(&outbuf, "%s%s%s", outbuf.len ? "\n" : "",
+ PREFIX, buf + 1);
+ retval = SIDEBAND_REMOTE_ERROR;
+ break;
case 2:
- buf[7] = ' ';
- len += 8;
- while (1) {
- int brk = 8;
- while (brk < len) {
- brk++;
- if (buf[brk-1] == '\n' ||
- buf[brk-1] == '\r')
- break;
+ b = buf + 1;
+
+ /*
+ * Append a suffix to each nonempty line to clear the
+ * end of the screen line.
+ *
+ * The output is accumulated in a buffer and
+ * each line is printed to stderr using
+ * write(2) to ensure inter-process atomicity.
+ */
+ while ((brk = strpbrk(b, "\n\r"))) {
+ int linelen = brk - b;
+
+ if (!outbuf.len)
+ strbuf_addstr(&outbuf, PREFIX);
+ if (linelen > 0) {
+ strbuf_addf(&outbuf, "%.*s%s%c",
+ linelen, b, suffix, *brk);
+ } else {
+ strbuf_addch(&outbuf, *brk);
}
- safe_write(err, buf, brk);
- if (brk < len) {
- memmove(buf + 8, buf + brk, len - brk);
- len = len - brk + 8;
- } else
- break;
+ xwrite(2, outbuf.buf, outbuf.len);
+ strbuf_reset(&outbuf);
+
+ b = brk + 1;
}
- continue;
+
+ if (*b)
+ strbuf_addf(&outbuf, "%s%s",
+ outbuf.len ? "" : PREFIX, b);
+ break;
case 1:
- safe_write(out, buf+8, len);
- continue;
+ write_or_die(out, buf + 1, len);
+ break;
default:
- len = sprintf(buf,
- "%s: protocol error: bad band #%d\n",
- me, band);
- safe_write(err, buf, len);
- return SIDEBAND_PROTOCOL_ERROR;
+ strbuf_addf(&outbuf, "%s%s: protocol error: bad band #%d",
+ outbuf.len ? "\n" : "", me, band);
+ retval = SIDEBAND_PROTOCOL_ERROR;
+ break;
}
}
- return 0;
+
+ if (outbuf.len) {
+ strbuf_addch(&outbuf, '\n');
+ xwrite(2, outbuf.buf, outbuf.len);
+ }
+ strbuf_release(&outbuf);
+ return retval;
}
/*
* fd is connected to the remote side; send the sideband data
* over multiplexed packet stream.
*/
-ssize_t send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max)
+void send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max)
{
- ssize_t ssz = sz;
const char *p = data;
while (sz) {
n = sz;
if (packet_max - 5 < n)
n = packet_max - 5;
- sprintf(hdr, "%04x", n + 5);
- hdr[4] = band;
- safe_write(fd, hdr, 5);
- safe_write(fd, p, n);
+ if (0 <= band) {
+ xsnprintf(hdr, sizeof(hdr), "%04x", n + 5);
+ hdr[4] = band;
+ write_or_die(fd, hdr, 5);
+ } else {
+ xsnprintf(hdr, sizeof(hdr), "%04x", n + 4);
+ write_or_die(fd, hdr, 4);
+ }
+ write_or_die(fd, p, n);
p += n;
sz -= n;
}
- return ssz;
}