]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/con/xms.c
devproc: can't wait for ourselfs to stop (thanks Shamar)
[plan9front.git] / sys / src / cmd / con / xms.c
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 }