1 #include <u.h> 2 #include <libc.h> 3 #include <ctype.h> 4 5 enum { 6 Soh= 0x1, 7 Stx= 0x2, 8 Eot= 0x4, 9 Ack= 0x6, 10 Nak= 0x15, 11 Cancel= 0x18, 12 }; 13 14 int send(uchar*, int); 15 int notifyf(void*, char*); 16 17 int debug, progress, onek; 18 19 void 20 errorout(int ctl, int bytes) 21 { 22 uchar buf[2]; 23 24 buf[0] = Cancel; 25 write(1, buf, 1); 26 fprint(2, "\nxms: gave up after %d bytes\n", bytes); 27 write(ctl, "rawoff", 6); 28 exits("cancel"); 29 } 30 31 ushort 32 updcrc(int c, ushort crc) 33 { 34 int count; 35 36 for (count=8; --count>=0;) { 37 if (crc & 0x8000) { 38 crc <<= 1; 39 crc += (((c<<=1) & 0400) != 0); 40 crc ^= 0x1021; 41 } 42 else { 43 crc <<= 1; 44 crc += (((c<<=1) & 0400) != 0); 45 } 46 } 47 return crc; 48 } 49 50 void 51 main(int argc, char **argv) 52 { 53 uchar c; 54 uchar buf[1024+5]; 55 uchar seqno; 56 int fd, ctl; 57 long n; 58 int sum; 59 uchar *p; 60 int bytes; 61 int crcmode; 62 63 ARGBEGIN{ 64 case 'd': 65 debug = 1; 66 break; 67 case 'p': 68 progress = 1; 69 break; 70 case '1': 71 onek = 1; 72 break; 73 }ARGEND 74 75 if(argc != 1){ 76 fprint(2, "usage: xms filename\n"); 77 exits("usage"); 78 } 79 fd = open(argv[0], OREAD); 80 if(fd < 0){ 81 perror("xms"); 82 exits("open"); 83 } 84 85 ctl = open("/dev/consctl", OWRITE); 86 if(ctl < 0){ 87 perror("xms"); 88 exits("consctl"); 89 } 90 write(ctl, "rawon", 5); 91 92 /* give the other side a 30 seconds to signal ready */ 93 atnotify(notifyf, 1); 94 alarm(30*1000); 95 crcmode = 0; 96 for(;;){ 97 if(read(0, &c, 1) != 1){ 98 fprint(2, "xms: timeout\n"); 99 exits("timeout"); 100 } 101 c = c & 0x7f; 102 if(c == Nak) 103 break; 104 if(c == 'C') { 105 if (debug) 106 fprint(2, "crc mode engaged\n"); 107 crcmode = 1; 108 break; 109 } 110 } 111 alarm(0); 112 113 /* send the file in 128/1024 byte chunks */ 114 for(bytes = 0, seqno = 1; ; bytes += n, seqno++){ 115 n = read(fd, buf+3, onek ? 1024 : 128); 116 if(n < 0) 117 exits("read"); 118 if(n == 0) 119 break; 120 if(n < (onek ? 1024 : 128)) 121 memset(&buf[n+3], 0, (onek ? 1024 : 128)-n); 122 buf[0] = onek ? Stx : Soh; 123 buf[1] = seqno; 124 buf[2] = 255 - seqno; 125 126 /* calculate checksum and stuff into last byte */ 127 if (crcmode) { 128 unsigned short crc; 129 crc = 0; 130 for(p = buf + 3; p < &buf[(onek ? 1024 : 128)+3]; p++) 131 crc = updcrc(*p, crc); 132 crc = updcrc(0, crc); 133 crc = updcrc(0, crc); 134 buf[(onek ? 1024 : 128) + 3] = crc >> 8; 135 buf[(onek ? 1024 : 128) + 4] = crc; 136 } 137 else { 138 sum = 0; 139 for(p = buf + 3; p < &buf[(onek ? 1024 : 128)+3]; p++) 140 sum += *p; 141 buf[(onek ? 1024 : 128) + 3] = sum; 142 } 143 144 if(send(buf, (onek ? 1024 : 128) + 4 + crcmode) < 0) 145 errorout(ctl, bytes); 146 if (progress && bytes % 10240 == 0) 147 fprint(2, "%dK\n", bytes / 1024); 148 } 149 150 /* tell other side we're done */ 151 buf[0] = Eot; 152 if(send(buf, 1) < 0) 153 errorout(ctl, bytes); 154 155 fprint(2, "xms: %d bytes transmitted\n", bytes); 156 write(ctl, "rawoff", 6); 157 exits(0); 158 } 159 160 /* 161 * send a message till it's acked or we give up 162 */ 163 int 164 send(uchar *buf, int len) 165 { 166 int tries; 167 int n; 168 uchar c; 169 170 for(tries = 0;; tries++, sleep(2*1000)){ 171 if(tries == 10) 172 return -1; 173 if(write(1, buf, len) != len) 174 return -1; 175 176 alarm(30*1000); 177 n = read(0, &c, 1); 178 alarm(0); 179 if(debug) switch(c){ 180 case Soh: 181 fprint(2, " Soh"); 182 break; 183 case Eot: 184 fprint(2, " Eot"); 185 break; 186 case Ack: 187 fprint(2, " Ack"); 188 break; 189 case Nak: 190 fprint(2, " Nak"); 191 break; 192 case Cancel: 193 fprint(2, "\nremote Cancel\n"); 194 return -1; 195 default: 196 if(isprint(c)) 197 fprint(2, "%c", c); 198 else 199 fprint(2, " \\0%o", c); 200 } 201 c = c & 0x7f; 202 if(n == 1 && c == Ack) 203 break; 204 } 205 return 0; 206 } 207 208 int 209 notifyf(void *a, char *msg) 210 { 211 USED(a); 212 if(strcmp(msg, "alarm") == 0) 213 return 1; 214 return 0; 215 } 216