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
errorout(int ctl,int bytes)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
updcrc(int c,ushort crc)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
main(int argc,char ** argv)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
send(uchar * buf,int len)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
notifyf(void * a,char * msg)209 notifyf(void *a, char *msg)
210 {
211 USED(a);
212 if(strcmp(msg, "alarm") == 0)
213 return 1;
214 return 0;
215 }
216