plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }