1#include"cache.h" 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 */ 15 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 23intrecv_sideband(const char*me,int in_stream,int out) 24{ 25unsigned pf =strlen(PREFIX); 26unsigned sf; 27char buf[LARGE_PACKET_MAX +2*FIX_SIZE]; 28char*suffix, *term; 29int skip_pf =0; 30 31memcpy(buf, PREFIX, pf); 32 term =getenv("TERM"); 33if(isatty(2) && term &&strcmp(term,"dumb")) 34 suffix = ANSI_SUFFIX; 35else 36 suffix = DUMB_SUFFIX; 37 sf =strlen(suffix); 38 39while(1) { 40int band, len; 41 len =packet_read(in_stream, NULL, NULL, buf + pf, LARGE_PACKET_MAX,0); 42if(len ==0) 43break; 44if(len <1) { 45fprintf(stderr,"%s: protocol error: no band designator\n", me); 46return SIDEBAND_PROTOCOL_ERROR; 47} 48 band = buf[pf] &0xff; 49 len--; 50switch(band) { 51case3: 52 buf[pf] =' '; 53 buf[pf+1+len] ='\0'; 54fprintf(stderr,"%s\n", buf); 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); 98fprintf(stderr,"%.*s", brk + sf, b); 99memcpy(b + brk, save, sf); 100 len -= brk; 101}else{ 102int l = brk ? brk : len; 103fprintf(stderr,"%.*s", l, b); 104 len -= l; 105} 106 107 skip_pf = !brk; 108memmove(buf + pf+1, b + brk, len); 109}while(len); 110continue; 111case1: 112write_or_die(out, buf + pf+1, len); 113continue; 114default: 115fprintf(stderr,"%s: protocol error: bad band #%d\n", 116 me, band); 117return SIDEBAND_PROTOCOL_ERROR; 118} 119} 120return0; 121} 122 123/* 124 * fd is connected to the remote side; send the sideband data 125 * over multiplexed packet stream. 126 */ 127voidsend_sideband(int fd,int band,const char*data, ssize_t sz,int packet_max) 128{ 129const char*p = data; 130 131while(sz) { 132unsigned n; 133char hdr[5]; 134 135 n = sz; 136if(packet_max -5< n) 137 n = packet_max -5; 138if(0<= band) { 139xsnprintf(hdr,sizeof(hdr),"%04x", n +5); 140 hdr[4] = band; 141write_or_die(fd, hdr,5); 142}else{ 143xsnprintf(hdr,sizeof(hdr),"%04x", n +4); 144write_or_die(fd, hdr,4); 145} 146write_or_die(fd, p, n); 147 p += n; 148 sz -= n; 149} 150}