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