1eba00c11SDavid du Colombier /*
2*68de9c93SDavid du Colombier * cec — coraid ethernet console
3*68de9c93SDavid du Colombier * Copyright © Coraid, Inc. 2006-2008.
4*68de9c93SDavid du Colombier * All Rights Reserved.
5eba00c11SDavid du Colombier */
6eba00c11SDavid du Colombier #include <u.h>
7eba00c11SDavid du Colombier #include <libc.h>
8eba00c11SDavid du Colombier #include <ip.h> /* really! */
9eba00c11SDavid du Colombier #include <ctype.h>
10eba00c11SDavid du Colombier #include "cec.h"
11eba00c11SDavid du Colombier
12eba00c11SDavid du Colombier enum {
13eba00c11SDavid du Colombier Tinita = 0,
14eba00c11SDavid du Colombier Tinitb,
15eba00c11SDavid du Colombier Tinitc,
16eba00c11SDavid du Colombier Tdata,
17eba00c11SDavid du Colombier Tack,
18eba00c11SDavid du Colombier Tdiscover,
19eba00c11SDavid du Colombier Toffer,
20eba00c11SDavid du Colombier Treset,
21eba00c11SDavid du Colombier
22*68de9c93SDavid du Colombier Hdrsz = 18,
23eba00c11SDavid du Colombier Eaddrlen = 6,
24eba00c11SDavid du Colombier };
25eba00c11SDavid du Colombier
26*68de9c93SDavid du Colombier typedef struct{
27eba00c11SDavid du Colombier uchar ea[Eaddrlen];
28*68de9c93SDavid du Colombier int major;
29*68de9c93SDavid du Colombier char name[28];
30*68de9c93SDavid du Colombier } Shelf;
31eba00c11SDavid du Colombier
32*68de9c93SDavid du Colombier int conn(int);
33eba00c11SDavid du Colombier void gettingkilled(int);
34eba00c11SDavid du Colombier int pickone(void);
35eba00c11SDavid du Colombier void probe(void);
36eba00c11SDavid du Colombier void sethdr(Pkt *, int);
37eba00c11SDavid du Colombier int shelfidx(void);
38eba00c11SDavid du Colombier
39*68de9c93SDavid du Colombier Shelf *con;
40*68de9c93SDavid du Colombier Shelf tab[1000];
41*68de9c93SDavid du Colombier
42*68de9c93SDavid du Colombier char *host;
43*68de9c93SDavid du Colombier char *srv;
44*68de9c93SDavid du Colombier char *svc;
45*68de9c93SDavid du Colombier
46*68de9c93SDavid du Colombier char pflag;
47*68de9c93SDavid du Colombier
48*68de9c93SDavid du Colombier int ntab;
49*68de9c93SDavid du Colombier int shelf = -1;
50*68de9c93SDavid du Colombier
51*68de9c93SDavid du Colombier uchar bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
52*68de9c93SDavid du Colombier uchar contag;
53*68de9c93SDavid du Colombier uchar esc = '';
54*68de9c93SDavid du Colombier uchar ea[Eaddrlen];
55*68de9c93SDavid du Colombier uchar unsetea[Eaddrlen];
56*68de9c93SDavid du Colombier
57eba00c11SDavid du Colombier extern int fd; /* set in netopen */
58eba00c11SDavid du Colombier
59*68de9c93SDavid du Colombier void
post(char * srv,int fd)60*68de9c93SDavid du Colombier post(char *srv, int fd)
61*68de9c93SDavid du Colombier {
62*68de9c93SDavid du Colombier char buf[32];
63*68de9c93SDavid du Colombier int f;
64*68de9c93SDavid du Colombier
65*68de9c93SDavid du Colombier if((f = create(srv, OWRITE, 0666)) == -1)
66*68de9c93SDavid du Colombier sysfatal("create %s: %r", srv);
67*68de9c93SDavid du Colombier snprint(buf, sizeof buf, "%d", fd);
68*68de9c93SDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf))
69*68de9c93SDavid du Colombier sysfatal("write %s: %r", srv);
70*68de9c93SDavid du Colombier close(f);
71*68de9c93SDavid du Colombier }
72*68de9c93SDavid du Colombier
73*68de9c93SDavid du Colombier void
dosrv(char * s)74*68de9c93SDavid du Colombier dosrv(char *s)
75*68de9c93SDavid du Colombier {
76*68de9c93SDavid du Colombier int p[2];
77*68de9c93SDavid du Colombier
78*68de9c93SDavid du Colombier if(pipe(p) < 0)
79*68de9c93SDavid du Colombier sysfatal("pipe: %r");
80*68de9c93SDavid du Colombier if (srv[0] != '/')
81*68de9c93SDavid du Colombier svc = smprint("/srv/%s", s);
82*68de9c93SDavid du Colombier else
83*68de9c93SDavid du Colombier svc = smprint("%s", s);
84*68de9c93SDavid du Colombier post(svc, p[0]);
85*68de9c93SDavid du Colombier close(p[0]);
86*68de9c93SDavid du Colombier dup(p[1], 0);
87*68de9c93SDavid du Colombier dup(p[1], 1);
88*68de9c93SDavid du Colombier
89*68de9c93SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
90*68de9c93SDavid du Colombier case -1:
91*68de9c93SDavid du Colombier sysfatal("fork: %r");
92*68de9c93SDavid du Colombier case 0:
93*68de9c93SDavid du Colombier break;
94*68de9c93SDavid du Colombier default:
95*68de9c93SDavid du Colombier exits("");
96*68de9c93SDavid du Colombier }
97*68de9c93SDavid du Colombier close(2);
98*68de9c93SDavid du Colombier }
99eba00c11SDavid du Colombier
100eba00c11SDavid du Colombier void
usage(void)101eba00c11SDavid du Colombier usage(void)
102eba00c11SDavid du Colombier {
103*68de9c93SDavid du Colombier fprint(2, "usage: cec [-dp] [-c esc] [-e ea] [-h host] [-s shelf] "
104*68de9c93SDavid du Colombier "[-S srv] interface\n");
105eba00c11SDavid du Colombier exits0("usage");
106eba00c11SDavid du Colombier }
107eba00c11SDavid du Colombier
108eba00c11SDavid du Colombier void
catch(void *,char * note)109eba00c11SDavid du Colombier catch(void*, char *note)
110eba00c11SDavid du Colombier {
111eba00c11SDavid du Colombier if(strcmp(note, "alarm") == 0)
112eba00c11SDavid du Colombier noted(NCONT);
113eba00c11SDavid du Colombier noted(NDFLT);
114eba00c11SDavid du Colombier }
115eba00c11SDavid du Colombier
116*68de9c93SDavid du Colombier int
nilea(uchar * ea)117*68de9c93SDavid du Colombier nilea(uchar *ea)
118*68de9c93SDavid du Colombier {
119*68de9c93SDavid du Colombier return memcmp(ea, unsetea, Eaddrlen) == 0;
120*68de9c93SDavid du Colombier }
121*68de9c93SDavid du Colombier
122eba00c11SDavid du Colombier void
main(int argc,char ** argv)123eba00c11SDavid du Colombier main(int argc, char **argv)
124eba00c11SDavid du Colombier {
125eba00c11SDavid du Colombier int r, n;
126eba00c11SDavid du Colombier
127eba00c11SDavid du Colombier ARGBEGIN{
128*68de9c93SDavid du Colombier case 'S':
129*68de9c93SDavid du Colombier srv = EARGF(usage());
130*68de9c93SDavid du Colombier break;
131*68de9c93SDavid du Colombier case 'c':
132*68de9c93SDavid du Colombier esc = tolower(*(EARGF(usage()))) - 'a' + 1;
133*68de9c93SDavid du Colombier if(esc == 0 || esc >= ' ')
134*68de9c93SDavid du Colombier usage();
135*68de9c93SDavid du Colombier break;
136eba00c11SDavid du Colombier case 'd':
137eba00c11SDavid du Colombier debug++;
138eba00c11SDavid du Colombier break;
139*68de9c93SDavid du Colombier case 'e':
140*68de9c93SDavid du Colombier if(parseether(ea, EARGF(usage())) == -1)
141*68de9c93SDavid du Colombier usage();
142*68de9c93SDavid du Colombier pflag = 1;
143*68de9c93SDavid du Colombier break;
144*68de9c93SDavid du Colombier case 'h':
145*68de9c93SDavid du Colombier host = EARGF(usage());
146*68de9c93SDavid du Colombier break;
147*68de9c93SDavid du Colombier case 'p':
148*68de9c93SDavid du Colombier pflag = 1;
149*68de9c93SDavid du Colombier break;
150eba00c11SDavid du Colombier case 's':
151eba00c11SDavid du Colombier shelf = atoi(EARGF(usage()));
152eba00c11SDavid du Colombier break;
153eba00c11SDavid du Colombier default:
154eba00c11SDavid du Colombier usage();
155eba00c11SDavid du Colombier }ARGEND
156*68de9c93SDavid du Colombier if(argc == 0)
157*68de9c93SDavid du Colombier *argv = "/net/ether0";
158*68de9c93SDavid du Colombier else if(argc != 1)
159eba00c11SDavid du Colombier usage();
160eba00c11SDavid du Colombier
161eba00c11SDavid du Colombier fmtinstall('E', eipfmt);
162*68de9c93SDavid du Colombier if(srv != nil)
163*68de9c93SDavid du Colombier dosrv(srv);
164eba00c11SDavid du Colombier r = netopen(*argv);
165eba00c11SDavid du Colombier if(r == -1){
166eba00c11SDavid du Colombier fprint(2, "cec: can't netopen %s\n", *argv);
167eba00c11SDavid du Colombier exits0("open");
168eba00c11SDavid du Colombier }
169eba00c11SDavid du Colombier notify(catch);
170eba00c11SDavid du Colombier probe();
171eba00c11SDavid du Colombier for(;;){
172eba00c11SDavid du Colombier n = 0;
173*68de9c93SDavid du Colombier if(shelf == -1 && host == 0 && nilea(ea))
174eba00c11SDavid du Colombier n = pickone();
175eba00c11SDavid du Colombier rawon();
176eba00c11SDavid du Colombier conn(n);
177eba00c11SDavid du Colombier rawoff();
178*68de9c93SDavid du Colombier if(pflag == 0){
179eba00c11SDavid du Colombier if(shelf != -1)
180eba00c11SDavid du Colombier exits0("shelf not found");
181*68de9c93SDavid du Colombier if(host)
182*68de9c93SDavid du Colombier exits0("host not found");
183*68de9c93SDavid du Colombier if(!nilea(ea))
184*68de9c93SDavid du Colombier exits0("ea not found");
185*68de9c93SDavid du Colombier } else if(shelf != -1 || host || !nilea(ea))
186*68de9c93SDavid du Colombier exits0("");
187eba00c11SDavid du Colombier }
188eba00c11SDavid du Colombier }
189eba00c11SDavid du Colombier
190eba00c11SDavid du Colombier void
timewait(int ms)191*68de9c93SDavid du Colombier timewait(int ms)
192eba00c11SDavid du Colombier {
193eba00c11SDavid du Colombier alarm(ms);
194eba00c11SDavid du Colombier }
195eba00c11SDavid du Colombier
196eba00c11SDavid du Colombier int
didtimeout(void)197eba00c11SDavid du Colombier didtimeout(void)
198eba00c11SDavid du Colombier {
199eba00c11SDavid du Colombier char buf[ERRMAX];
200eba00c11SDavid du Colombier
201eba00c11SDavid du Colombier rerrstr(buf, sizeof buf);
202eba00c11SDavid du Colombier if(strcmp(buf, "interrupted") == 0){
203eba00c11SDavid du Colombier werrstr(buf, 0);
204eba00c11SDavid du Colombier return 1;
205eba00c11SDavid du Colombier }
206eba00c11SDavid du Colombier return 0;
207eba00c11SDavid du Colombier }
208eba00c11SDavid du Colombier
209eba00c11SDavid du Colombier ushort
htons(ushort h)210eba00c11SDavid du Colombier htons(ushort h)
211eba00c11SDavid du Colombier {
212eba00c11SDavid du Colombier ushort n;
213eba00c11SDavid du Colombier uchar *p;
214eba00c11SDavid du Colombier
215eba00c11SDavid du Colombier p = (uchar*)&n;
216eba00c11SDavid du Colombier p[0] = h >> 8;
217eba00c11SDavid du Colombier p[1] = h;
218eba00c11SDavid du Colombier return n;
219eba00c11SDavid du Colombier }
220eba00c11SDavid du Colombier
221eba00c11SDavid du Colombier ushort
ntohs(int h)222eba00c11SDavid du Colombier ntohs(int h)
223eba00c11SDavid du Colombier {
224eba00c11SDavid du Colombier ushort n;
225eba00c11SDavid du Colombier uchar *p;
226eba00c11SDavid du Colombier
227eba00c11SDavid du Colombier n = h;
228eba00c11SDavid du Colombier p = (uchar*)&n;
229eba00c11SDavid du Colombier return p[0] << 8 | p[1];
230eba00c11SDavid du Colombier }
231eba00c11SDavid du Colombier
232*68de9c93SDavid du Colombier int
tcmp(void * a,void * b)233*68de9c93SDavid du Colombier tcmp(void *a, void *b)
234*68de9c93SDavid du Colombier {
235*68de9c93SDavid du Colombier Shelf *s, *t;
236*68de9c93SDavid du Colombier int d;
237*68de9c93SDavid du Colombier
238*68de9c93SDavid du Colombier s = a;
239*68de9c93SDavid du Colombier t = b;
240*68de9c93SDavid du Colombier d = s->major - t->major;
241*68de9c93SDavid du Colombier if(d == 0)
242*68de9c93SDavid du Colombier d = strcmp(s->name, t->name);
243*68de9c93SDavid du Colombier if(d == 0)
244*68de9c93SDavid du Colombier d = memcmp(s->ea, t->ea, Eaddrlen);
245*68de9c93SDavid du Colombier return d;
246*68de9c93SDavid du Colombier }
247*68de9c93SDavid du Colombier
248eba00c11SDavid du Colombier void
probe(void)249eba00c11SDavid du Colombier probe(void)
250eba00c11SDavid du Colombier {
251eba00c11SDavid du Colombier char *sh, *other;
252*68de9c93SDavid du Colombier int n;
253eba00c11SDavid du Colombier Pkt q;
254eba00c11SDavid du Colombier Shelf *p;
255eba00c11SDavid du Colombier
256*68de9c93SDavid du Colombier do {
257eba00c11SDavid du Colombier ntab = 0;
258eba00c11SDavid du Colombier memset(q.dst, 0xff, Eaddrlen);
259eba00c11SDavid du Colombier memset(q.src, 0, Eaddrlen);
260eba00c11SDavid du Colombier q.etype = htons(Etype);
261eba00c11SDavid du Colombier q.type = Tdiscover;
262eba00c11SDavid du Colombier q.len = 0;
263eba00c11SDavid du Colombier q.conn = 0;
264eba00c11SDavid du Colombier q.seq = 0;
265eba00c11SDavid du Colombier netsend(&q, 60);
266eba00c11SDavid du Colombier timewait(Iowait);
267eba00c11SDavid du Colombier while((n = netget(&q, sizeof q)) >= 0){
268eba00c11SDavid du Colombier if((n <= 0 && didtimeout()) || ntab == nelem(tab))
269eba00c11SDavid du Colombier break;
270eba00c11SDavid du Colombier if(n < 60 || q.len == 0 || q.type != Toffer)
271eba00c11SDavid du Colombier continue;
272eba00c11SDavid du Colombier q.data[q.len] = 0;
273eba00c11SDavid du Colombier sh = strtok((char *)q.data, " \t");
274eba00c11SDavid du Colombier if(sh == nil)
275eba00c11SDavid du Colombier continue;
276*68de9c93SDavid du Colombier if(!nilea(ea) && memcmp(ea, q.src, Eaddrlen) != 0)
277*68de9c93SDavid du Colombier continue;
278eba00c11SDavid du Colombier if(shelf != -1 && atoi(sh) != shelf)
279eba00c11SDavid du Colombier continue;
280eba00c11SDavid du Colombier other = strtok(nil, "\x1");
281*68de9c93SDavid du Colombier if(other == 0)
282*68de9c93SDavid du Colombier other = "";
283*68de9c93SDavid du Colombier if(host && strcmp(host, other) != 0)
284*68de9c93SDavid du Colombier continue;
285eba00c11SDavid du Colombier p = tab + ntab++;
286eba00c11SDavid du Colombier memcpy(p->ea, q.src, Eaddrlen);
287*68de9c93SDavid du Colombier p->major = atoi(sh);
288*68de9c93SDavid du Colombier p->name[0] = 0;
289*68de9c93SDavid du Colombier if(p->name)
290*68de9c93SDavid du Colombier snprint(p->name, sizeof p->name, "%s", other);
291eba00c11SDavid du Colombier }
292eba00c11SDavid du Colombier alarm(0);
293*68de9c93SDavid du Colombier } while (ntab == 0 && pflag);
294eba00c11SDavid du Colombier if(ntab == 0){
295eba00c11SDavid du Colombier fprint(2, "none found.\n");
296eba00c11SDavid du Colombier exits0("none found");
297eba00c11SDavid du Colombier }
298*68de9c93SDavid du Colombier qsort(tab, ntab, sizeof tab[0], tcmp);
299eba00c11SDavid du Colombier }
300eba00c11SDavid du Colombier
301eba00c11SDavid du Colombier void
showtable(void)302eba00c11SDavid du Colombier showtable(void)
303eba00c11SDavid du Colombier {
304eba00c11SDavid du Colombier int i;
305eba00c11SDavid du Colombier
306eba00c11SDavid du Colombier for(i = 0; i < ntab; i++)
307*68de9c93SDavid du Colombier print("%2d %5d %E %s\n", i, tab[i].major, tab[i].ea, tab[i].name);
308eba00c11SDavid du Colombier }
309eba00c11SDavid du Colombier
310eba00c11SDavid du Colombier int
pickone(void)311eba00c11SDavid du Colombier pickone(void)
312eba00c11SDavid du Colombier {
313eba00c11SDavid du Colombier char buf[80];
314eba00c11SDavid du Colombier int n, i;
315eba00c11SDavid du Colombier
316eba00c11SDavid du Colombier for(;;){
317eba00c11SDavid du Colombier showtable();
318eba00c11SDavid du Colombier print("[#qp]: ");
319eba00c11SDavid du Colombier switch(n = read(0, buf, sizeof buf)){
320eba00c11SDavid du Colombier case 1:
321eba00c11SDavid du Colombier if(buf[0] == '\n')
322eba00c11SDavid du Colombier continue;
323eba00c11SDavid du Colombier /* fall through */
324eba00c11SDavid du Colombier case 2:
325eba00c11SDavid du Colombier if(buf[0] == 'p'){
326eba00c11SDavid du Colombier probe();
327eba00c11SDavid du Colombier break;
328eba00c11SDavid du Colombier }
329eba00c11SDavid du Colombier if(buf[0] == 'q')
330eba00c11SDavid du Colombier /* fall through */
331eba00c11SDavid du Colombier case 0:
332eba00c11SDavid du Colombier case -1:
333eba00c11SDavid du Colombier exits0(0);
334*68de9c93SDavid du Colombier break;
335eba00c11SDavid du Colombier }
336eba00c11SDavid du Colombier if(isdigit(buf[0])){
337eba00c11SDavid du Colombier buf[n] = 0;
338eba00c11SDavid du Colombier i = atoi(buf);
339eba00c11SDavid du Colombier if(i >= 0 && i < ntab)
340eba00c11SDavid du Colombier break;
341eba00c11SDavid du Colombier }
342eba00c11SDavid du Colombier }
343eba00c11SDavid du Colombier return i;
344eba00c11SDavid du Colombier }
345eba00c11SDavid du Colombier
346eba00c11SDavid du Colombier void
sethdr(Pkt * pp,int type)347eba00c11SDavid du Colombier sethdr(Pkt *pp, int type)
348eba00c11SDavid du Colombier {
349*68de9c93SDavid du Colombier memmove(pp->dst, con->ea, Eaddrlen);
350eba00c11SDavid du Colombier memset(pp->src, 0, Eaddrlen);
351eba00c11SDavid du Colombier pp->etype = htons(Etype);
352eba00c11SDavid du Colombier pp->type = type;
353eba00c11SDavid du Colombier pp->len = 0;
354eba00c11SDavid du Colombier pp->conn = contag;
355eba00c11SDavid du Colombier }
356eba00c11SDavid du Colombier
357eba00c11SDavid du Colombier void
ethclose(void)358eba00c11SDavid du Colombier ethclose(void)
359eba00c11SDavid du Colombier {
360eba00c11SDavid du Colombier static Pkt msg;
361eba00c11SDavid du Colombier
362eba00c11SDavid du Colombier sethdr(&msg, Treset);
363eba00c11SDavid du Colombier timewait(Iowait);
364eba00c11SDavid du Colombier netsend(&msg, 60);
365eba00c11SDavid du Colombier alarm(0);
366*68de9c93SDavid du Colombier con = 0;
367eba00c11SDavid du Colombier }
368eba00c11SDavid du Colombier
369eba00c11SDavid du Colombier int
ethopen(void)370eba00c11SDavid du Colombier ethopen(void)
371eba00c11SDavid du Colombier {
372eba00c11SDavid du Colombier Pkt tpk, rpk;
373eba00c11SDavid du Colombier int i, n;
374eba00c11SDavid du Colombier
375eba00c11SDavid du Colombier contag = (getpid() >> 8) ^ (getpid() & 0xff);
376eba00c11SDavid du Colombier sethdr(&tpk, Tinita);
377eba00c11SDavid du Colombier sethdr(&rpk, 0);
378eba00c11SDavid du Colombier for(i = 0; i < 3 && rpk.type != Tinitb; i++){
379eba00c11SDavid du Colombier netsend(&tpk, 60);
380eba00c11SDavid du Colombier timewait(Iowait);
381eba00c11SDavid du Colombier n = netget(&rpk, 1000);
382eba00c11SDavid du Colombier alarm(0);
383eba00c11SDavid du Colombier if(n < 0)
384eba00c11SDavid du Colombier return -1;
385eba00c11SDavid du Colombier }
386eba00c11SDavid du Colombier if(rpk.type != Tinitb)
387eba00c11SDavid du Colombier return -1;
388eba00c11SDavid du Colombier sethdr(&tpk, Tinitc);
389eba00c11SDavid du Colombier netsend(&tpk, 60);
390eba00c11SDavid du Colombier return 0;
391eba00c11SDavid du Colombier }
392eba00c11SDavid du Colombier
393eba00c11SDavid du Colombier char
escape(void)394eba00c11SDavid du Colombier escape(void)
395eba00c11SDavid du Colombier {
396eba00c11SDavid du Colombier char buf[64];
397*68de9c93SDavid du Colombier int r;
398eba00c11SDavid du Colombier
399eba00c11SDavid du Colombier for(;;){
400eba00c11SDavid du Colombier fprint(2, ">>> ");
401eba00c11SDavid du Colombier buf[0] = '.';
402eba00c11SDavid du Colombier rawoff();
403*68de9c93SDavid du Colombier r = read(0, buf, sizeof buf - 1);
404eba00c11SDavid du Colombier rawon();
405*68de9c93SDavid du Colombier if(r == -1)
406*68de9c93SDavid du Colombier exits0("kbd: %r");
407eba00c11SDavid du Colombier switch(buf[0]){
408eba00c11SDavid du Colombier case 'i':
409eba00c11SDavid du Colombier case 'q':
410eba00c11SDavid du Colombier case '.':
411eba00c11SDavid du Colombier return buf[0];
412eba00c11SDavid du Colombier }
413eba00c11SDavid du Colombier fprint(2, " (q)uit, (i)nterrupt, (.)continue\n");
414eba00c11SDavid du Colombier }
415eba00c11SDavid du Colombier }
416eba00c11SDavid du Colombier
417eba00c11SDavid du Colombier /*
418*68de9c93SDavid du Colombier * this is a bit too aggressive. it really needs to replace only \n\r with \n.
419eba00c11SDavid du Colombier */
420*68de9c93SDavid du Colombier static uchar crbuf[256];
421eba00c11SDavid du Colombier
422eba00c11SDavid du Colombier void
nocrwrite(int fd,uchar * buf,int n)423eba00c11SDavid du Colombier nocrwrite(int fd, uchar *buf, int n)
424eba00c11SDavid du Colombier {
425eba00c11SDavid du Colombier int i, j, c;
426eba00c11SDavid du Colombier
427eba00c11SDavid du Colombier j = 0;
428*68de9c93SDavid du Colombier for(i = 0; i < n; i++)
429*68de9c93SDavid du Colombier if((c = buf[i]) != '\r')
430eba00c11SDavid du Colombier crbuf[j++] = c;
431eba00c11SDavid du Colombier write(fd, crbuf, j);
432eba00c11SDavid du Colombier }
433eba00c11SDavid du Colombier
434eba00c11SDavid du Colombier int
doloop(void)435eba00c11SDavid du Colombier doloop(void)
436eba00c11SDavid du Colombier {
437eba00c11SDavid du Colombier int unacked, retries, set[2];
438eba00c11SDavid du Colombier uchar c, tseq, rseq;
439eba00c11SDavid du Colombier uchar ea[Eaddrlen];
440eba00c11SDavid du Colombier Pkt tpk, spk;
441*68de9c93SDavid du Colombier Mux *m;
442eba00c11SDavid du Colombier
443*68de9c93SDavid du Colombier memmove(ea, con->ea, Eaddrlen);
444eba00c11SDavid du Colombier retries = 0;
445eba00c11SDavid du Colombier unacked = 0;
446eba00c11SDavid du Colombier tseq = 0;
447eba00c11SDavid du Colombier rseq = -1;
448eba00c11SDavid du Colombier set[0] = 0;
449eba00c11SDavid du Colombier set[1] = fd;
450eba00c11SDavid du Colombier top:
451eba00c11SDavid du Colombier if ((m = mux(set)) == 0)
452eba00c11SDavid du Colombier exits0("mux: %r");
453eba00c11SDavid du Colombier for (; ; )
454eba00c11SDavid du Colombier switch (muxread(m, &spk)) {
455eba00c11SDavid du Colombier case -1:
456eba00c11SDavid du Colombier if (unacked == 0)
457eba00c11SDavid du Colombier break;
458eba00c11SDavid du Colombier if (retries-- == 0) {
459eba00c11SDavid du Colombier fprint(2, "Connection timed out\n");
460eba00c11SDavid du Colombier muxfree(m);
461eba00c11SDavid du Colombier return 0;
462eba00c11SDavid du Colombier }
463*68de9c93SDavid du Colombier netsend(&tpk, Hdrsz + unacked);
464eba00c11SDavid du Colombier break;
465*68de9c93SDavid du Colombier case Fkbd:
466eba00c11SDavid du Colombier c = spk.data[0];
467eba00c11SDavid du Colombier if (c == esc) {
468eba00c11SDavid du Colombier muxfree(m);
469eba00c11SDavid du Colombier switch (escape()) {
470eba00c11SDavid du Colombier case 'q':
471eba00c11SDavid du Colombier tpk.len = 0;
472eba00c11SDavid du Colombier tpk.type = Treset;
473eba00c11SDavid du Colombier netsend(&tpk, 60);
474eba00c11SDavid du Colombier return 0;
475eba00c11SDavid du Colombier case '.':
476eba00c11SDavid du Colombier goto top;
477eba00c11SDavid du Colombier case 'i':
478eba00c11SDavid du Colombier if ((m = mux(set)) == 0)
479eba00c11SDavid du Colombier exits0("mux: %r");
480eba00c11SDavid du Colombier break;
481eba00c11SDavid du Colombier }
482eba00c11SDavid du Colombier }
483eba00c11SDavid du Colombier sethdr(&tpk, Tdata);
484eba00c11SDavid du Colombier memcpy(tpk.data, spk.data, spk.len);
485eba00c11SDavid du Colombier tpk.len = spk.len;
486eba00c11SDavid du Colombier tpk.seq = ++tseq;
487eba00c11SDavid du Colombier unacked = spk.len;
488eba00c11SDavid du Colombier retries = 2;
489*68de9c93SDavid du Colombier netsend(&tpk, Hdrsz + spk.len);
490eba00c11SDavid du Colombier break;
491*68de9c93SDavid du Colombier case Fcec:
492eba00c11SDavid du Colombier if (memcmp(spk.src, ea, Eaddrlen) != 0 ||
493eba00c11SDavid du Colombier ntohs(spk.etype) != Etype)
494eba00c11SDavid du Colombier continue;
495*68de9c93SDavid du Colombier if (spk.type == Toffer &&
496*68de9c93SDavid du Colombier memcmp(spk.dst, bcast, Eaddrlen) != 0) {
497eba00c11SDavid du Colombier muxfree(m);
498eba00c11SDavid du Colombier return 1;
499eba00c11SDavid du Colombier }
500eba00c11SDavid du Colombier if (spk.conn != contag)
501eba00c11SDavid du Colombier continue;
502eba00c11SDavid du Colombier switch (spk.type) {
503eba00c11SDavid du Colombier case Tdata:
504eba00c11SDavid du Colombier if (spk.seq == rseq)
505eba00c11SDavid du Colombier break;
506eba00c11SDavid du Colombier nocrwrite(1, spk.data, spk.len);
507eba00c11SDavid du Colombier memmove(spk.dst, spk.src, Eaddrlen);
508eba00c11SDavid du Colombier memset(spk.src, 0, Eaddrlen);
509eba00c11SDavid du Colombier spk.type = Tack;
510eba00c11SDavid du Colombier spk.len = 0;
511eba00c11SDavid du Colombier rseq = spk.seq;
512eba00c11SDavid du Colombier netsend(&spk, 60);
513eba00c11SDavid du Colombier break;
514eba00c11SDavid du Colombier case Tack:
515eba00c11SDavid du Colombier if (spk.seq == tseq)
516eba00c11SDavid du Colombier unacked = 0;
517eba00c11SDavid du Colombier break;
518eba00c11SDavid du Colombier case Treset:
519eba00c11SDavid du Colombier muxfree(m);
520eba00c11SDavid du Colombier return 1;
521eba00c11SDavid du Colombier }
522*68de9c93SDavid du Colombier break;
523*68de9c93SDavid du Colombier case Ffatal:
524*68de9c93SDavid du Colombier muxfree(m);
525*68de9c93SDavid du Colombier fprint(2, "kbd read error\n");
526*68de9c93SDavid du Colombier exits0("fatal");
527eba00c11SDavid du Colombier }
528eba00c11SDavid du Colombier }
529eba00c11SDavid du Colombier
530*68de9c93SDavid du Colombier int
conn(int n)531eba00c11SDavid du Colombier conn(int n)
532eba00c11SDavid du Colombier {
533*68de9c93SDavid du Colombier int r;
534*68de9c93SDavid du Colombier
535*68de9c93SDavid du Colombier for(;;){
536*68de9c93SDavid du Colombier if(con)
537eba00c11SDavid du Colombier ethclose();
538*68de9c93SDavid du Colombier con = tab + n;
539eba00c11SDavid du Colombier if(ethopen() < 0){
540*68de9c93SDavid du Colombier fprint(2, "connection failed\n");
541*68de9c93SDavid du Colombier return 0;
542eba00c11SDavid du Colombier }
543*68de9c93SDavid du Colombier r = doloop();
544*68de9c93SDavid du Colombier if(r <= 0)
545*68de9c93SDavid du Colombier return r;
546*68de9c93SDavid du Colombier }
547eba00c11SDavid du Colombier }
548eba00c11SDavid du Colombier
549eba00c11SDavid du Colombier void
exits0(char * s)550eba00c11SDavid du Colombier exits0(char *s)
551eba00c11SDavid du Colombier {
552*68de9c93SDavid du Colombier if(con != nil)
553eba00c11SDavid du Colombier ethclose();
554eba00c11SDavid du Colombier rawoff();
555*68de9c93SDavid du Colombier if(svc != nil)
556*68de9c93SDavid du Colombier remove(svc);
557eba00c11SDavid du Colombier exits(s);
558eba00c11SDavid du Colombier }
559