Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <venti.h>
5 static char *okvers[] = {
6 "04",
7 "02",
8 nil,
9 };
11 /*
12 static char EBigString[] = "string too long";
13 static char EBigPacket[] = "packet too long";
14 static char ENullString[] = "missing string";
15 */
16 static char EBadVersion[] = "bad format in version string";
18 static int
19 vtreadversion(VtConn *z, char *q, char *v, int nv)
20 {
21 int n;
23 for(;;){
24 if(nv <= 1){
25 werrstr("version too long");
26 return -1;
27 }
28 n = read(z->infd, v, 1);
29 if(n <= 0){
30 if(n == 0)
31 werrstr("unexpected eof");
32 return -1;
33 }
34 if(*v == '\n'){
35 *v = 0;
36 break;
37 }
38 if((uchar)*v < ' ' || (uchar)*v > 0x7f || (*q && *v != *q)){
39 werrstr(EBadVersion);
40 return -1;
41 }
42 v++;
43 nv--;
44 if(*q)
45 q++;
46 }
47 return 0;
48 }
50 int
51 vtversion(VtConn *z)
52 {
53 char buf[VtMaxStringSize], *p, *ep, *prefix, *pp;
54 int i;
56 qlock(&z->lk);
57 if(z->state != VtStateAlloc){
58 werrstr("bad session state");
59 qunlock(&z->lk);
60 return -1;
61 }
63 qlock(&z->inlk);
64 qlock(&z->outlk);
66 p = buf;
67 ep = buf + sizeof buf;
68 prefix = "venti-";
69 p = seprint(p, ep, "%s", prefix);
70 p += strlen(p);
71 for(i=0; okvers[i]; i++)
72 p = seprint(p, ep, "%s%s", i ? ":" : "", okvers[i]);
73 p = seprint(p, ep, "-libventi\n");
74 assert(p-buf < sizeof buf);
76 if(write(z->outfd, buf, p-buf) != p-buf)
77 goto Err;
78 vtdebug(z, "version string out: %s", buf);
80 if(vtreadversion(z, prefix, buf, sizeof buf) < 0)
81 goto Err;
82 vtdebug(z, "version string in: %s", buf);
84 p = buf+strlen(prefix);
85 for(; *p; p=pp){
86 if(*p == ':' || *p == '-')
87 p++;
88 pp = strpbrk(p, ":-");
89 if(pp == nil)
90 pp = p+strlen(p);
91 for(i=0; okvers[i]; i++)
92 if(strlen(okvers[i]) == pp-p && memcmp(okvers[i], p, pp-p) == 0){
93 *pp = 0;
94 z->version = vtstrdup(p);
95 goto Okay;
96 }
97 }
98 werrstr("unable to negotiate version");
99 goto Err;
101 Okay:
102 z->state = VtStateConnected;
103 qunlock(&z->inlk);
104 qunlock(&z->outlk);
105 qunlock(&z->lk);
106 return 0;
108 Err:
109 werrstr("vtversion: %r");
110 if(z->infd >= 0)
111 close(z->infd);
112 if(z->outfd >= 0 && z->outfd != z->infd)
113 close(z->outfd);
114 z->infd = -1;
115 z->outfd = -1;
116 z->state = VtStateClosed;
117 qunlock(&z->inlk);
118 qunlock(&z->outlk);
119 qunlock(&z->lk);
120 return -1;