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
/*