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