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 } 121