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 22intrecv_sideband(const char*me,int in_stream,int out,int err) 23{ 24unsigned pf =strlen(PREFIX); 25unsigned sf; 26char buf[LARGE_PACKET_MAX +2*FIX_SIZE]; 27char*suffix, *term; 28int skip_pf =0; 29 30memcpy(buf, PREFIX, pf); 31 term =getenv("TERM"); 32if(term &&strcmp(term,"dumb")) 33 suffix = ANSI_SUFFIX; 34else 35 suffix = DUMB_SUFFIX; 36 sf =strlen(suffix); 37 38while(1) { 39int band, len; 40 len =packet_read_line(in_stream, buf + pf, LARGE_PACKET_MAX); 41if(len ==0) 42break; 43if(len <1) { 44 len =sprintf(buf,"%s: protocol error: no band designator\n", me); 45safe_write(err, buf, len); 46return SIDEBAND_PROTOCOL_ERROR; 47} 48 band = buf[pf] &0xff; 49 len--; 50switch(band) { 51case3: 52 buf[pf] =' '; 53 buf[pf+1+len] ='\n'; 54safe_write(err, buf, pf+1+len+1); 55return SIDEBAND_REMOTE_ERROR; 56case2: 57 buf[pf] =' '; 58do{ 59char*b = buf; 60int brk =0; 61 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 */ 67if(skip_pf) { 68 b += pf+1; 69}else{ 70 len += pf+1; 71 brk += pf+1; 72} 73 74/* Look for a line break. */ 75for(;;) { 76 brk++; 77if(brk > len) { 78 brk =0; 79break; 80} 81if(b[brk-1] =='\n'|| 82 b[brk-1] =='\r') 83break; 84} 85 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 */ 93if(brk > (skip_pf ?0: (pf+1+1))) { 94char save[FIX_SIZE]; 95memcpy(save, b + brk, sf); 96 b[brk + sf -1] = b[brk -1]; 97memcpy(b + brk -1, suffix, sf); 98safe_write(err, b, brk + sf); 99memcpy(b + brk, save, sf); 100 len -= brk; 101}else{ 102int l = brk ? brk : len; 103safe_write(err, b, l); 104 len -= l; 105} 106 107 skip_pf = !brk; 108memmove(buf + pf+1, b + brk, len); 109}while(len); 110continue; 111case1: 112safe_write(out, buf + pf+1, len); 113continue; 114default: 115 len =sprintf(buf, 116"%s: protocol error: bad band #%d\n", 117 me, band); 118safe_write(err, buf, len); 119return SIDEBAND_PROTOCOL_ERROR; 120} 121} 122return0; 123} 124 125/* 126 * fd is connected to the remote side; send the sideband data 127 * over multiplexed packet stream. 128 */ 129ssize_t send_sideband(int fd,int band,const char*data, ssize_t sz,int packet_max) 130{ 131 ssize_t ssz = sz; 132const char*p = data; 133 134while(sz) { 135unsigned n; 136char hdr[5]; 137 138 n = sz; 139if(packet_max -5< n) 140 n = packet_max -5; 141sprintf(hdr,"%04x", n +5); 142 hdr[4] = band; 143safe_write(fd, hdr,5); 144safe_write(fd, p, n); 145 p += n; 146 sz -= n; 147} 148return ssz; 149}