Merge git://git.kernel.org/pub/scm/gitk/gitk
[git] / sideband.c
1 #include "pkt-line.h"
2 #include "sideband.h"
3
4 /*
5  * Receive multiplexed output stream over git native protocol.
6  * in_stream is the input stream from the remote, which carries data
7  * in pkt_line format with band designator.  Demultiplex it into out
8  * and err and return error appropriately.  Band #1 carries the
9  * primary payload.  Things coming over band #2 is not necessarily
10  * error; they are usually informative message on the standard error
11  * stream, aka "verbose").  A message over band #3 is a signal that
12  * the remote died unexpectedly.  A flush() concludes the stream.
13  */
14
15 #define PREFIX "remote:"
16
17 #define ANSI_SUFFIX "\033[K"
18 #define DUMB_SUFFIX "        "
19
20 #define FIX_SIZE 10  /* large enough for any of the above */
21
22 int recv_sideband(const char *me, int in_stream, int out, int err)
23 {
24         unsigned pf = strlen(PREFIX);
25         unsigned sf;
26         char buf[LARGE_PACKET_MAX + 2*FIX_SIZE];
27         char *suffix, *term;
28
29         memcpy(buf, PREFIX, pf);
30         term = getenv("TERM");
31         if (term && strcmp(term, "dumb"))
32                 suffix = ANSI_SUFFIX;
33         else
34                 suffix = DUMB_SUFFIX;
35         sf = strlen(suffix);
36
37         while (1) {
38                 int band, len;
39                 len = packet_read_line(in_stream, buf + pf, LARGE_PACKET_MAX);
40                 if (len == 0)
41                         break;
42                 if (len < 1) {
43                         len = sprintf(buf, "%s: protocol error: no band designator\n", me);
44                         safe_write(err, buf, len);
45                         return SIDEBAND_PROTOCOL_ERROR;
46                 }
47                 band = buf[pf] & 0xff;
48                 len--;
49                 switch (band) {
50                 case 3:
51                         buf[pf] = ' ';
52                         buf[pf+1+len] = '\n';
53                         safe_write(err, buf, pf+1+len+1);
54                         return SIDEBAND_REMOTE_ERROR;
55                 case 2:
56                         buf[pf] = ' ';
57                         len += pf+1;
58                         while (1) {
59                                 int brk = pf+1;
60
61                                 /* Break the buffer into separate lines. */
62                                 while (brk < len) {
63                                         brk++;
64                                         if (buf[brk-1] == '\n' ||
65                                             buf[brk-1] == '\r')
66                                                 break;
67                                 }
68
69                                 /*
70                                  * Let's insert a suffix to clear the end
71                                  * of the screen line, but only if current
72                                  * line data actually contains something.
73                                  */
74                                 if (brk > pf+1 + 1) {
75                                         char save[FIX_SIZE];
76                                         memcpy(save, buf + brk, sf);
77                                         buf[brk + sf - 1] = buf[brk - 1];
78                                         memcpy(buf + brk - 1, suffix, sf);
79                                         safe_write(err, buf, brk + sf);
80                                         memcpy(buf + brk, save, sf);
81                                 } else
82                                         safe_write(err, buf, brk);
83
84                                 if (brk < len) {
85                                         memmove(buf + pf+1, buf + brk, len - brk);
86                                         len = len - brk + pf+1;
87                                 } else
88                                         break;
89                         }
90                         continue;
91                 case 1:
92                         safe_write(out, buf + pf+1, len);
93                         continue;
94                 default:
95                         len = sprintf(buf,
96                                       "%s: protocol error: bad band #%d\n",
97                                       me, band);
98                         safe_write(err, buf, len);
99                         return SIDEBAND_PROTOCOL_ERROR;
100                 }
101         }
102         return 0;
103 }
104
105 /*
106  * fd is connected to the remote side; send the sideband data
107  * over multiplexed packet stream.
108  */
109 ssize_t send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max)
110 {
111         ssize_t ssz = sz;
112         const char *p = data;
113
114         while (sz) {
115                 unsigned n;
116                 char hdr[5];
117
118                 n = sz;
119                 if (packet_max - 5 < n)
120                         n = packet_max - 5;
121                 sprintf(hdr, "%04x", n + 5);
122                 hdr[4] = band;
123                 safe_write(fd, hdr, 5);
124                 safe_write(fd, p, n);
125                 p += n;
126                 sz -= n;
127         }
128         return ssz;
129 }