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>

Lukas Fleischer committed Jun 28, 2016 at 06:35 UTC 5e5be9e257239b3599701f05518ce9e45f565e9f
1 file changed +58 -74
sideband.c
+58 -74
@@ -13,111 +13,95 @@
13 * the remote died unexpectedly. A flush() concludes the stream.
14 */
15
16 -#define PREFIX "remote:"
16 +#define PREFIX "remote: "
17
18 #define ANSI_SUFFIX "\033[K"
19 #define DUMB_SUFFIX " "
20
21 -#define FIX_SIZE 10 /* large enough for any of the above */
22 -
21 int recv_sideband(const char *me, int in_stream, int out)
22 {
25 - unsigned pf = strlen(PREFIX);
26 - unsigned sf;
27 - char buf[LARGE_PACKET_MAX + 2*FIX_SIZE];
28 - char *suffix, *term;
29 - int skip_pf = 0;
23 + const char *term, *suffix;
24 + char buf[LARGE_PACKET_MAX + 1];
25 + struct strbuf outbuf = STRBUF_INIT;
26 + int retval = 0;
27
31 - memcpy(buf, PREFIX, pf);
28 term = getenv("TERM");
29 if (isatty(2) && term && strcmp(term, "dumb"))
30 suffix = ANSI_SUFFIX;
31 else
32 suffix = DUMB_SUFFIX;
37 - sf = strlen(suffix);
33
39 - while (1) {
34 + while (!retval) {
35 + const char *b, *brk;
36 int band, len;
41 - len = packet_read(in_stream, NULL, NULL, buf + pf, LARGE_PACKET_MAX, 0);
37 + len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX, 0);
38 if (len == 0)
39 break;
40 if (len < 1) {
45 - fprintf(stderr, "%s: protocol error: no band designator\n", me);
46 - return SIDEBAND_PROTOCOL_ERROR;
41 + strbuf_addf(&outbuf,
42 + "%s%s: protocol error: no band designator",
43 + outbuf.len ? "\n" : "", me);
44 + retval = SIDEBAND_PROTOCOL_ERROR;
45 + break;
46 }
48 - band = buf[pf] & 0xff;
47 + band = buf[0] & 0xff;
48 + buf[len] = '\0';
49 len--;
50 switch (band) {
51 case 3:
52 - buf[pf] = ' ';
53 - buf[pf+1+len] = '\0';
54 - fprintf(stderr, "%s\n", buf);
55 - return SIDEBAND_REMOTE_ERROR;
52 + strbuf_addf(&outbuf, "%s%s%s", outbuf.len ? "\n" : "",
53 + PREFIX, buf + 1);
54 + retval = SIDEBAND_REMOTE_ERROR;
55 + break;
56 case 2:
57 - buf[pf] = ' ';
58 - do {
59 - char *b = buf;
60 - int brk = 0;
57 + b = buf + 1;
58
62 - /*
63 - * If the last buffer didn't end with a line
64 - * break then we should not print a prefix
65 - * this time around.
66 - */
67 - if (skip_pf) {
68 - b += pf+1;
69 - } else {
70 - len += pf+1;
71 - brk += pf+1;
72 - }
73 -
74 - /* Look for a line break. */
75 - for (;;) {
76 - brk++;
77 - if (brk > len) {
78 - brk = 0;
79 - break;
80 - }
81 - if (b[brk-1] == '\n' ||
82 - b[brk-1] == '\r')
83 - break;
84 - }
59 + /*
60 + * Append a suffix to each nonempty line to clear the
61 + * end of the screen line.
62 + *
63 + * The output is accumulated in a buffer and
64 + * each line is printed to stderr using
65 + * write(2) to ensure inter-process atomicity.
66 + */
67 + while ((brk = strpbrk(b, "\n\r"))) {
68 + int linelen = brk - b;
69
86 - /*
87 - * Let's insert a suffix to clear the end
88 - * of the screen line if a line break was
89 - * found. Also, if we don't skip the
90 - * prefix, then a non-empty string must be
91 - * present too.
92 - */
93 - if (brk > (skip_pf ? 0 : (pf+1 + 1))) {
94 - char save[FIX_SIZE];
95 - memcpy(save, b + brk, sf);
96 - b[brk + sf - 1] = b[brk - 1];
97 - memcpy(b + brk - 1, suffix, sf);
98 - fprintf(stderr, "%.*s", brk + sf, b);
99 - memcpy(b + brk, save, sf);
100 - len -= brk;
70 + if (!outbuf.len)
71 + strbuf_addf(&outbuf, "%s", PREFIX);
72 + if (linelen > 0) {
73 + strbuf_addf(&outbuf, "%.*s%s%c",
74 + linelen, b, suffix, *brk);
75 } else {
102 - int l = brk ? brk : len;
103 - fprintf(stderr, "%.*s", l, b);
104 - len -= l;
76 + strbuf_addf(&outbuf, "%c", *brk);
77 }
78 + xwrite(2, outbuf.buf, outbuf.len);
79 + strbuf_reset(&outbuf);
80
107 - skip_pf = !brk;
108 - memmove(buf + pf+1, b + brk, len);
109 - } while (len);
110 - continue;
81 + b = brk + 1;
82 + }
83 +
84 + if (*b)
85 + strbuf_addf(&outbuf, "%s%s",
86 + outbuf.len ? "" : PREFIX, b);
87 + break;
88 case 1:
112 - write_or_die(out, buf + pf+1, len);
113 - continue;
89 + write_or_die(out, buf + 1, len);
90 + break;
91 default:
115 - fprintf(stderr, "%s: protocol error: bad band #%d\n",
116 - me, band);
117 - return SIDEBAND_PROTOCOL_ERROR;
92 + strbuf_addf(&outbuf, "%s%s: protocol error: bad band #%d",
93 + outbuf.len ? "\n" : "", me, band);
94 + retval = SIDEBAND_PROTOCOL_ERROR;
95 + break;
96 }
97 }
120 - return 0;
98 +
99 + if (outbuf.len) {
100 + strbuf_addf(&outbuf, "\n");
101 + xwrite(2, outbuf.buf, outbuf.len);
102 + }
103 + strbuf_release(&outbuf);
104 + return retval;
105 }
106
107 /*