X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=sideband.c;h=cca3360546dabf9f018b882f690bd1dea9de534d;hb=a786091b4a487bc08bbff4864717cf5d8383e983;hp=ab8a1e990db39155efc624ca99e85c1cf8eaefa9;hpb=a130976b71f36c73fc6279fd02beb1f798d82487;p=git.git diff --git a/sideband.c b/sideband.c index ab8a1e990..cca336054 100644 --- a/sideband.c +++ b/sideband.c @@ -11,13 +11,33 @@ * stream, aka "verbose"). A message over band #3 is a signal that * the remote died unexpectedly. A flush() concludes the stream. */ + +#define PREFIX "remote:" + +#define ANSI_SUFFIX "\033[K" +#define DUMB_SUFFIX " " + +#define FIX_SIZE 10 /* large enough for any of the above */ + int recv_sideband(const char *me, int in_stream, int out, int err) { - char buf[7 + LARGE_PACKET_MAX + 1]; - strcpy(buf, "remote:"); + unsigned pf = strlen(PREFIX); + unsigned sf; + char buf[LARGE_PACKET_MAX + 2*FIX_SIZE]; + char *suffix, *term; + int skip_pf = 0; + + memcpy(buf, PREFIX, pf); + term = getenv("TERM"); + if (term && strcmp(term, "dumb")) + suffix = ANSI_SUFFIX; + else + suffix = DUMB_SUFFIX; + sf = strlen(suffix); + while (1) { int band, len; - len = packet_read_line(in_stream, buf+7, LARGE_PACKET_MAX); + len = packet_read_line(in_stream, buf + pf, LARGE_PACKET_MAX); if (len == 0) break; if (len < 1) { @@ -25,35 +45,71 @@ int recv_sideband(const char *me, int in_stream, int out, int err) safe_write(err, buf, len); return SIDEBAND_PROTOCOL_ERROR; } - band = buf[7] & 0xff; + band = buf[pf] & 0xff; len--; switch (band) { case 3: - buf[7] = ' '; - buf[8+len] = '\n'; - safe_write(err, buf, 8+len+1); + buf[pf] = ' '; + buf[pf+1+len] = '\n'; + safe_write(err, buf, pf+1+len+1); return SIDEBAND_REMOTE_ERROR; case 2: - buf[7] = ' '; - len += 8; - while (1) { - int brk = 8; - while (brk < len) { + buf[pf] = ' '; + do { + char *b = buf; + int brk = 0; + + /* + * If the last buffer didn't end with a line + * break then we should not print a prefix + * this time around. + */ + if (skip_pf) { + b += pf+1; + } else { + len += pf+1; + brk += pf+1; + } + + /* Look for a line break. */ + for (;;) { brk++; - if (buf[brk-1] == '\n' || - buf[brk-1] == '\r') + if (brk > len) { + brk = 0; + break; + } + if (b[brk-1] == '\n' || + b[brk-1] == '\r') break; } - safe_write(err, buf, brk); - if (brk < len) { - memmove(buf + 8, buf + brk, len - brk); - len = len - brk + 8; - } else - break; - } + + /* + * Let's insert a suffix to clear the end + * of the screen line if a line break was + * found. Also, if we don't skip the + * prefix, then a non-empty string must be + * present too. + */ + if (brk > (skip_pf ? 0 : (pf+1 + 1))) { + char save[FIX_SIZE]; + memcpy(save, b + brk, sf); + b[brk + sf - 1] = b[brk - 1]; + memcpy(b + brk - 1, suffix, sf); + safe_write(err, b, brk + sf); + memcpy(b + brk, save, sf); + len -= brk; + } else { + int l = brk ? brk : len; + safe_write(err, b, l); + len -= l; + } + + skip_pf = !brk; + memmove(buf + pf+1, b + brk, len); + } while (len); continue; case 1: - safe_write(out, buf+8, len); + safe_write(out, buf + pf+1, len); continue; default: len = sprintf(buf,