Jeff King | cdf4fb8 | 2013-02-20 15:01:56 -0500 | [diff] [blame] | 1 | #include "cache.h" |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 2 | #include "pkt-line.h" |
| 3 | #include "sideband.h" |
| 4 | |
| 5 | /* |
| 6 | * Receive multiplexed output stream over git native protocol. |
| 7 | * in_stream is the input stream from the remote, which carries data |
| 8 | * in pkt_line format with band designator. Demultiplex it into out |
| 9 | * and err and return error appropriately. Band #1 carries the |
| 10 | * primary payload. Things coming over band #2 is not necessarily |
| 11 | * error; they are usually informative message on the standard error |
| 12 | * stream, aka "verbose"). A message over band #3 is a signal that |
| 13 | * the remote died unexpectedly. A flush() concludes the stream. |
| 14 | */ |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 15 | |
| 16 | #define PREFIX "remote:" |
Johannes Sixt | 13e4760 | 2008-01-08 17:24:53 +0100 | [diff] [blame] | 17 | |
| 18 | #define ANSI_SUFFIX "\033[K" |
| 19 | #define DUMB_SUFFIX " " |
| 20 | |
| 21 | #define FIX_SIZE 10 /* large enough for any of the above */ |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 22 | |
Johannes Sixt | 34df8ab | 2009-03-10 22:54:17 +0100 | [diff] [blame] | 23 | int recv_sideband(const char *me, int in_stream, int out) |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 24 | { |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 25 | unsigned pf = strlen(PREFIX); |
Johannes Sixt | 13e4760 | 2008-01-08 17:24:53 +0100 | [diff] [blame] | 26 | unsigned sf; |
| 27 | char buf[LARGE_PACKET_MAX + 2*FIX_SIZE]; |
| 28 | char *suffix, *term; |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 29 | int skip_pf = 0; |
Johannes Sixt | 13e4760 | 2008-01-08 17:24:53 +0100 | [diff] [blame] | 30 | |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 31 | memcpy(buf, PREFIX, pf); |
Johannes Sixt | 13e4760 | 2008-01-08 17:24:53 +0100 | [diff] [blame] | 32 | term = getenv("TERM"); |
Michael Naumov | 38de156 | 2014-05-28 03:12:15 +0000 | [diff] [blame] | 33 | if (isatty(2) && term && strcmp(term, "dumb")) |
Johannes Sixt | 13e4760 | 2008-01-08 17:24:53 +0100 | [diff] [blame] | 34 | suffix = ANSI_SUFFIX; |
| 35 | else |
| 36 | suffix = DUMB_SUFFIX; |
| 37 | sf = strlen(suffix); |
| 38 | |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 39 | while (1) { |
Nicolas Pitre | 9ac13ec | 2006-10-11 11:49:15 -0400 | [diff] [blame] | 40 | int band, len; |
Jeff King | 4981fe7 | 2013-02-23 17:31:34 -0500 | [diff] [blame] | 41 | len = packet_read(in_stream, NULL, NULL, buf + pf, LARGE_PACKET_MAX, 0); |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 42 | if (len == 0) |
| 43 | break; |
| 44 | if (len < 1) { |
Johannes Sixt | 34df8ab | 2009-03-10 22:54:17 +0100 | [diff] [blame] | 45 | fprintf(stderr, "%s: protocol error: no band designator\n", me); |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 46 | return SIDEBAND_PROTOCOL_ERROR; |
| 47 | } |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 48 | band = buf[pf] & 0xff; |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 49 | len--; |
Nicolas Pitre | 9ac13ec | 2006-10-11 11:49:15 -0400 | [diff] [blame] | 50 | switch (band) { |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 51 | case 3: |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 52 | buf[pf] = ' '; |
Johannes Sixt | 34df8ab | 2009-03-10 22:54:17 +0100 | [diff] [blame] | 53 | buf[pf+1+len] = '\0'; |
| 54 | fprintf(stderr, "%s\n", buf); |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 55 | return SIDEBAND_REMOTE_ERROR; |
| 56 | case 2: |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 57 | buf[pf] = ' '; |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 58 | do { |
| 59 | char *b = buf; |
| 60 | int brk = 0; |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 61 | |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 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 (;;) { |
Nicolas Pitre | ed1902e | 2007-10-16 21:55:46 -0400 | [diff] [blame] | 76 | brk++; |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 77 | if (brk > len) { |
| 78 | brk = 0; |
| 79 | break; |
| 80 | } |
| 81 | if (b[brk-1] == '\n' || |
| 82 | b[brk-1] == '\r') |
Nicolas Pitre | ed1902e | 2007-10-16 21:55:46 -0400 | [diff] [blame] | 83 | break; |
| 84 | } |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 85 | |
| 86 | /* |
| 87 | * Let's insert a suffix to clear the end |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 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. |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 92 | */ |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 93 | if (brk > (skip_pf ? 0 : (pf+1 + 1))) { |
Johannes Sixt | 13e4760 | 2008-01-08 17:24:53 +0100 | [diff] [blame] | 94 | char save[FIX_SIZE]; |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 95 | memcpy(save, b + brk, sf); |
| 96 | b[brk + sf - 1] = b[brk - 1]; |
| 97 | memcpy(b + brk - 1, suffix, sf); |
Johannes Sixt | 34df8ab | 2009-03-10 22:54:17 +0100 | [diff] [blame] | 98 | fprintf(stderr, "%.*s", brk + sf, b); |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 99 | memcpy(b + brk, save, sf); |
| 100 | len -= brk; |
| 101 | } else { |
| 102 | int l = brk ? brk : len; |
Johannes Sixt | 34df8ab | 2009-03-10 22:54:17 +0100 | [diff] [blame] | 103 | fprintf(stderr, "%.*s", l, b); |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 104 | len -= l; |
| 105 | } |
Nicolas Pitre | ebe8fa7 | 2007-11-04 00:22:42 -0400 | [diff] [blame] | 106 | |
Nicolas Pitre | 6b9c42b | 2008-09-03 15:13:42 -0400 | [diff] [blame] | 107 | skip_pf = !brk; |
| 108 | memmove(buf + pf+1, b + brk, len); |
| 109 | } while (len); |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 110 | continue; |
| 111 | case 1: |
Jeff King | cdf4fb8 | 2013-02-20 15:01:56 -0500 | [diff] [blame] | 112 | write_or_die(out, buf + pf+1, len); |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 113 | continue; |
| 114 | default: |
Johannes Sixt | 34df8ab | 2009-03-10 22:54:17 +0100 | [diff] [blame] | 115 | fprintf(stderr, "%s: protocol error: bad band #%d\n", |
| 116 | me, band); |
Junio C Hamano | 49a52b1 | 2006-09-10 01:06:33 -0700 | [diff] [blame] | 117 | return SIDEBAND_PROTOCOL_ERROR; |
| 118 | } |
| 119 | } |
| 120 | return 0; |
| 121 | } |
Junio C Hamano | 958c24b | 2006-09-10 03:20:24 -0700 | [diff] [blame] | 122 | |
| 123 | /* |
| 124 | * fd is connected to the remote side; send the sideband data |
| 125 | * over multiplexed packet stream. |
| 126 | */ |
| 127 | ssize_t send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max) |
| 128 | { |
| 129 | ssize_t ssz = sz; |
| 130 | const char *p = data; |
| 131 | |
| 132 | while (sz) { |
| 133 | unsigned n; |
| 134 | char hdr[5]; |
| 135 | |
| 136 | n = sz; |
| 137 | if (packet_max - 5 < n) |
| 138 | n = packet_max - 5; |
Shawn O. Pearce | de1a2fd | 2009-10-30 17:47:41 -0700 | [diff] [blame] | 139 | if (0 <= band) { |
Jeff King | 5096d49 | 2015-09-24 17:06:08 -0400 | [diff] [blame] | 140 | xsnprintf(hdr, sizeof(hdr), "%04x", n + 5); |
Shawn O. Pearce | de1a2fd | 2009-10-30 17:47:41 -0700 | [diff] [blame] | 141 | hdr[4] = band; |
Jeff King | cdf4fb8 | 2013-02-20 15:01:56 -0500 | [diff] [blame] | 142 | write_or_die(fd, hdr, 5); |
Shawn O. Pearce | de1a2fd | 2009-10-30 17:47:41 -0700 | [diff] [blame] | 143 | } else { |
Jeff King | 5096d49 | 2015-09-24 17:06:08 -0400 | [diff] [blame] | 144 | xsnprintf(hdr, sizeof(hdr), "%04x", n + 4); |
Jeff King | cdf4fb8 | 2013-02-20 15:01:56 -0500 | [diff] [blame] | 145 | write_or_die(fd, hdr, 4); |
Shawn O. Pearce | de1a2fd | 2009-10-30 17:47:41 -0700 | [diff] [blame] | 146 | } |
Jeff King | cdf4fb8 | 2013-02-20 15:01:56 -0500 | [diff] [blame] | 147 | write_or_die(fd, p, n); |
Junio C Hamano | 958c24b | 2006-09-10 03:20:24 -0700 | [diff] [blame] | 148 | p += n; |
| 149 | sz -= n; |
| 150 | } |
| 151 | return ssz; |
| 152 | } |