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