version.c (2181B)
1 #include <u.h> 2 #include <libc.h> 3 #include <venti.h> 4 5 static char *okvers[] = { 6 "04", 7 "02", 8 nil, 9 }; 10 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"; 17 18 static int 19 vtreadversion(VtConn *z, char *q, char *v, int nv) 20 { 21 int n; 22 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 } 49 50 int 51 vtversion(VtConn *z) 52 { 53 char buf[VtMaxStringSize], *p, *ep, *prefix, *pp; 54 int i; 55 56 qlock(&z->lk); 57 if(z->state != VtStateAlloc){ 58 werrstr("bad session state"); 59 qunlock(&z->lk); 60 return -1; 61 } 62 63 qlock(&z->inlk); 64 qlock(&z->outlk); 65 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); 75 76 if(write(z->outfd, buf, p-buf) != p-buf) 77 goto Err; 78 vtdebug(z, "version string out: %s", buf); 79 80 if(vtreadversion(z, prefix, buf, sizeof buf) < 0) 81 goto Err; 82 vtdebug(z, "version string in: %s", buf); 83 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; 100 101 Okay: 102 z->state = VtStateConnected; 103 qunlock(&z->inlk); 104 qunlock(&z->outlk); 105 qunlock(&z->lk); 106 return 0; 107 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; 121 }