]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/con/xmr.c
devproc: can't wait for ourselfs to stop (thanks Shamar)
[plan9front.git] / sys / src / cmd / con / xmr.c
1 #include <u.h>
2 #include <libc.h>
3
4 enum {
5         Soh=    0x1,
6         Eot=    0x4,
7         Ack=    0x6,
8         Nak=    0x15,
9         Cancel= 0x18,
10 };
11
12 int notifyf(void*, char*);
13 int readupto(uchar*, int);
14 int receive(int, uchar);
15 void send(int);
16
17 int debug, dfd;
18
19 void
20 main(int argc, char **argv)
21 {
22         int fd;
23         uchar seqno;
24         ulong bytes;
25
26         ARGBEGIN {
27         case 'd':
28                 dfd = 2;
29                 debug = 1;
30                 break;
31         } ARGEND
32
33         if(argc != 1){
34                 fprint(2, "usage: xmr filename\n");
35                 exits("usage");
36         }
37         fd = open("/dev/consctl", OWRITE);
38         if(fd >= 0)
39                 write(fd, "rawon", 5);
40         fd = create(argv[0], ORDWR, 0666);
41         if(fd < 0){
42                 perror("xmr: create");
43                 exits("create");
44         }
45
46         atnotify(notifyf, 1);
47         send(Nak);
48
49         /*
50          *  keep receiving till the other side gives up
51          */
52         bytes = 0;
53         for(seqno = 1; ; seqno++){
54                 if(receive(fd, seqno) == -1)
55                         break;
56                 bytes += 128;
57         }
58         fprint(2, "xmr: received %ld bytes\n", bytes);
59         exits(0);
60 }
61
62 void
63 send(int byte)
64 {
65         uchar c;
66
67         c = byte;
68         if(write(1, &c, 1) != 1){
69                 fprint(2, "xmr: hungup\n");
70                 exits("hangup");
71         }
72 }
73
74 int
75 readupto(uchar *a, int len)
76 {
77         int n;
78         int sofar;
79
80         for(sofar = 0; sofar < len; sofar += n){
81                 n = read(0, a, len-sofar);
82                 if(n <= 0){
83                         send(Nak);
84                         return sofar;
85                 }
86                 if(*a == Eot || *a == Cancel)
87                         return sofar + n;
88                 a += n;
89         }
90         return sofar;
91
92 }
93
94 int
95 receive(int fd, uchar seqno)
96 {
97         uchar buf[128+4];
98         uchar sum;
99         uchar *p;
100         int n;
101         int tries;
102         int have;
103
104         for(have = 0, tries = 0;; tries++){
105                 if(debug)
106                         fprint(dfd, "have == %d\n", have);
107                 if(tries > 10){
108                         fprint(2, "xmr: timed out\n");
109                         if(debug)
110                                 close(dfd);
111                         exits("timeout");
112                 }
113
114                 /* try to gather up a block */
115                 alarm(15*1000);
116                 n = readupto(&buf[have], 132-have);
117                 alarm(0);
118                 have += n;
119                 if(have){
120                         switch(buf[0]){
121                         case Eot:
122                                 send(Ack);
123                                 return -1;
124                         case Cancel:
125                                 fprint(2, "xmr: transfer aborted by sender\n");
126                                 exits("cancel");
127                         }
128                 }
129                 if(have != 132)
130                         continue;
131
132                 /* checksum */
133                 for(p = buf, sum = 0; p < &buf[128+3]; p++)
134                         sum += *p;
135
136                 /* If invalid block, resynchronize */
137                 if(buf[0] != Soh || buf[2] != (255-buf[1]) || sum != buf[131]){
138                         if(debug){
139                                 fprint(dfd, "resync %2.2ux %d %d %ux %ux\n", buf[0],
140                                         buf[1], buf[2], sum, buf[131]);
141                                 write(dfd, (char*)buf+3, 128);
142                                 fprint(dfd, "\n");
143                         }
144                         p = memchr(buf+1, Soh, 131);
145                         if(p){
146                                 have = 132-(p-buf);
147                                 memmove(buf, p, have);
148                         } else
149                                 have = 0;
150                         continue;
151                 }
152
153                 /* it's probably a real block, so dump it if there's an error */
154                 have = 0;
155
156                 /* if this is the last block, ack */
157                 if(buf[1] == seqno-1){
158                         tries = 0;
159                         send(Ack);
160                 }else if(buf[1] == seqno){
161                         if(debug)
162                                 fprint(dfd, "Ack\n");
163                         send(Ack);
164                         if(write(fd, buf+3, 128) != 128){
165                                 fprint(2, "xmr: abort, error writing file\n");
166                                 exits("write");
167                         }
168                         return 0;
169                 } else {
170                         send(Nak);
171                 }
172         }
173 }
174
175 int
176 notifyf(void *a, char *msg)
177 {
178         USED(a);
179         if(strcmp(msg, "alarm") == 0)
180                 return 1;
181         return 0;
182 }