sideband.c: refactor recv_sideband()
We used character buffer manipulations to split messages from the
sideband at line breaks and insert "remote: " at the beginning of
each line, using the packet size to determine the end of a message.
However, since it is safe to assume that diagnostic messages from
the sideband never contain NUL characters, we can also NUL-terminate
the buffer, use strpbrk() for splitting lines and use format strings
to insert the prefix, to make the code easier to read and maintain.
A strbuf is used for accumulating the output which is then printed
using a single write(2) call to ensure the atomicity of the output.
See 9ac13ec
(atomic write for sideband remote messages, 2006-10-11)
for details.
Helped-by: Jeff King <peff@peff.net>
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Nicolas Pitre <nico@fluxnic.net>
Signed-off-by: Lukas Fleischer <lfleischer@lfos.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
765428699a
commit
5e5be9e257
132
sideband.c
132
sideband.c
@ -13,111 +13,95 @@
|
|||||||
* the remote died unexpectedly. A flush() concludes the stream.
|
* the remote died unexpectedly. A flush() concludes the stream.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PREFIX "remote:"
|
#define PREFIX "remote: "
|
||||||
|
|
||||||
#define ANSI_SUFFIX "\033[K"
|
#define ANSI_SUFFIX "\033[K"
|
||||||
#define DUMB_SUFFIX " "
|
#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 recv_sideband(const char *me, int in_stream, int out)
|
||||||
{
|
{
|
||||||
unsigned pf = strlen(PREFIX);
|
const char *term, *suffix;
|
||||||
unsigned sf;
|
char buf[LARGE_PACKET_MAX + 1];
|
||||||
char buf[LARGE_PACKET_MAX + 2*FIX_SIZE];
|
struct strbuf outbuf = STRBUF_INIT;
|
||||||
char *suffix, *term;
|
int retval = 0;
|
||||||
int skip_pf = 0;
|
|
||||||
|
|
||||||
memcpy(buf, PREFIX, pf);
|
|
||||||
term = getenv("TERM");
|
term = getenv("TERM");
|
||||||
if (isatty(2) && term && strcmp(term, "dumb"))
|
if (isatty(2) && term && strcmp(term, "dumb"))
|
||||||
suffix = ANSI_SUFFIX;
|
suffix = ANSI_SUFFIX;
|
||||||
else
|
else
|
||||||
suffix = DUMB_SUFFIX;
|
suffix = DUMB_SUFFIX;
|
||||||
sf = strlen(suffix);
|
|
||||||
|
|
||||||
while (1) {
|
while (!retval) {
|
||||||
|
const char *b, *brk;
|
||||||
int band, len;
|
int band, len;
|
||||||
len = packet_read(in_stream, NULL, NULL, buf + pf, LARGE_PACKET_MAX, 0);
|
len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX, 0);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
break;
|
break;
|
||||||
if (len < 1) {
|
if (len < 1) {
|
||||||
fprintf(stderr, "%s: protocol error: no band designator\n", me);
|
strbuf_addf(&outbuf,
|
||||||
return SIDEBAND_PROTOCOL_ERROR;
|
"%s%s: protocol error: no band designator",
|
||||||
|
outbuf.len ? "\n" : "", me);
|
||||||
|
retval = SIDEBAND_PROTOCOL_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
band = buf[pf] & 0xff;
|
band = buf[0] & 0xff;
|
||||||
|
buf[len] = '\0';
|
||||||
len--;
|
len--;
|
||||||
switch (band) {
|
switch (band) {
|
||||||
case 3:
|
case 3:
|
||||||
buf[pf] = ' ';
|
strbuf_addf(&outbuf, "%s%s%s", outbuf.len ? "\n" : "",
|
||||||
buf[pf+1+len] = '\0';
|
PREFIX, buf + 1);
|
||||||
fprintf(stderr, "%s\n", buf);
|
retval = SIDEBAND_REMOTE_ERROR;
|
||||||
return SIDEBAND_REMOTE_ERROR;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
buf[pf] = ' ';
|
b = buf + 1;
|
||||||
do {
|
|
||||||
char *b = buf;
|
|
||||||
int brk = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the last buffer didn't end with a line
|
* Append a suffix to each nonempty line to clear the
|
||||||
* break then we should not print a prefix
|
* end of the screen line.
|
||||||
* this time around.
|
*
|
||||||
*/
|
* The output is accumulated in a buffer and
|
||||||
if (skip_pf) {
|
* each line is printed to stderr using
|
||||||
b += pf+1;
|
* write(2) to ensure inter-process atomicity.
|
||||||
|
*/
|
||||||
|
while ((brk = strpbrk(b, "\n\r"))) {
|
||||||
|
int linelen = brk - b;
|
||||||
|
|
||||||
|
if (!outbuf.len)
|
||||||
|
strbuf_addf(&outbuf, "%s", PREFIX);
|
||||||
|
if (linelen > 0) {
|
||||||
|
strbuf_addf(&outbuf, "%.*s%s%c",
|
||||||
|
linelen, b, suffix, *brk);
|
||||||
} else {
|
} else {
|
||||||
len += pf+1;
|
strbuf_addf(&outbuf, "%c", *brk);
|
||||||
brk += pf+1;
|
|
||||||
}
|
}
|
||||||
|
xwrite(2, outbuf.buf, outbuf.len);
|
||||||
|
strbuf_reset(&outbuf);
|
||||||
|
|
||||||
/* Look for a line break. */
|
b = brk + 1;
|
||||||
for (;;) {
|
}
|
||||||
brk++;
|
|
||||||
if (brk > len) {
|
|
||||||
brk = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (b[brk-1] == '\n' ||
|
|
||||||
b[brk-1] == '\r')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if (*b)
|
||||||
* Let's insert a suffix to clear the end
|
strbuf_addf(&outbuf, "%s%s",
|
||||||
* of the screen line if a line break was
|
outbuf.len ? "" : PREFIX, b);
|
||||||
* found. Also, if we don't skip the
|
break;
|
||||||
* 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);
|
|
||||||
fprintf(stderr, "%.*s", brk + sf, b);
|
|
||||||
memcpy(b + brk, save, sf);
|
|
||||||
len -= brk;
|
|
||||||
} else {
|
|
||||||
int l = brk ? brk : len;
|
|
||||||
fprintf(stderr, "%.*s", l, b);
|
|
||||||
len -= l;
|
|
||||||
}
|
|
||||||
|
|
||||||
skip_pf = !brk;
|
|
||||||
memmove(buf + pf+1, b + brk, len);
|
|
||||||
} while (len);
|
|
||||||
continue;
|
|
||||||
case 1:
|
case 1:
|
||||||
write_or_die(out, buf + pf+1, len);
|
write_or_die(out, buf + 1, len);
|
||||||
continue;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: protocol error: bad band #%d\n",
|
strbuf_addf(&outbuf, "%s%s: protocol error: bad band #%d",
|
||||||
me, band);
|
outbuf.len ? "\n" : "", me, band);
|
||||||
return SIDEBAND_PROTOCOL_ERROR;
|
retval = SIDEBAND_PROTOCOL_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
if (outbuf.len) {
|
||||||
|
strbuf_addf(&outbuf, "\n");
|
||||||
|
xwrite(2, outbuf.buf, outbuf.len);
|
||||||
|
}
|
||||||
|
strbuf_release(&outbuf);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user