aboutsummaryrefslogtreecommitdiff
path: root/src/libventi/version.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2003-11-23 18:19:58 +0000
committerrsc <devnull@localhost>2003-11-23 18:19:58 +0000
commit056fe1ba7fa0b70f871dfb9005b24eb8e4cc230b (patch)
tree9ad42f31c3bc124cf6617cf9eb41dd525eccce83 /src/libventi/version.c
parent9df487d720a59bf8cb0dc4ccffc30ad8eb48256a (diff)
downloadplan9port-056fe1ba7fa0b70f871dfb9005b24eb8e4cc230b.tar.gz
plan9port-056fe1ba7fa0b70f871dfb9005b24eb8e4cc230b.tar.bz2
plan9port-056fe1ba7fa0b70f871dfb9005b24eb8e4cc230b.zip
new venti library.
Diffstat (limited to 'src/libventi/version.c')
-rw-r--r--src/libventi/version.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/libventi/version.c b/src/libventi/version.c
new file mode 100644
index 00000000..dbbc4dc5
--- /dev/null
+++ b/src/libventi/version.c
@@ -0,0 +1,115 @@
+#include <u.h>
+#include <libc.h>
+#include <venti.h>
+
+static char *okvers[] = {
+ "02",
+ nil,
+};
+
+/*
+static char EBigString[] = "string too long";
+static char EBigPacket[] = "packet too long";
+static char ENullString[] = "missing string";
+*/
+static char EBadVersion[] = "bad format in version string";
+
+static int
+vtreadversion(VtConn *z, char *q, char *v, int nv)
+{
+ int n;
+
+ for(;;){
+ if(nv <= 1){
+ werrstr("version too long");
+ return -1;
+ }
+ n = read(z->infd, v, 1);
+ if(n <= 0){
+ if(n == 0)
+ werrstr("unexpected eof");
+ return -1;
+ }
+ if(*v == '\n'){
+ *v = 0;
+ break;
+ }
+ if((uchar)*v < ' ' || (uchar)*v > 0x7f || (*q && *v != *q)){
+ werrstr(EBadVersion);
+ return -1;
+ }
+ v++;
+ nv--;
+ if(*q)
+ q++;
+ }
+ return 0;
+}
+
+int
+vtversion(VtConn *z)
+{
+ char buf[VtMaxStringSize], *p, *ep, *prefix, *pp;
+ int i;
+
+ qlock(&z->lk);
+ if(z->state != VtStateAlloc){
+ werrstr("bad session state");
+ qunlock(&z->lk);
+ return -1;
+ }
+
+ qlock(&z->inlk);
+ qlock(&z->outlk);
+
+ p = buf;
+ ep = buf + sizeof buf;
+ prefix = "venti-";
+ p = seprint(p, ep, "%s", prefix);
+ p += strlen(p);
+ for(i=0; okvers[i]; i++)
+ p = seprint(p, ep, "%s%s", i ? ":" : "", okvers[i]);
+ p = seprint(p, ep, "-libventi\n");
+ assert(p-buf < sizeof buf);
+
+ if(write(z->outfd, buf, p-buf) != p-buf)
+ goto Err;
+ vtdebug(z, "version string out: %s", buf);
+
+ if(vtreadversion(z, prefix, buf, sizeof buf) < 0)
+ goto Err;
+ vtdebug(z, "version string in: %s", buf);
+
+ p = buf+strlen(prefix);
+ for(;;){
+ pp = strpbrk(p, ":-");
+ for(i=0; okvers[i]; i++)
+ if(strlen(okvers[i]) == pp-p && memcmp(okvers[i], p, pp-p) == 0){
+ *pp = 0;
+ z->version = vtstrdup(p);
+ goto Okay;
+ }
+ }
+ werrstr("unable to negotiate version");
+ goto Err;
+
+Okay:
+ z->state = VtStateConnected;
+ qunlock(&z->inlk);
+ qunlock(&z->outlk);
+ qunlock(&z->lk);
+ return 0;
+
+Err:
+ if(z->infd >= 0)
+ close(z->infd);
+ if(z->outfd >= 0 && z->outfd != z->infd)
+ close(z->outfd);
+ z->infd = -1;
+ z->outfd = -1;
+ z->state = VtStateClosed;
+ qunlock(&z->inlk);
+ qunlock(&z->outlk);
+ qunlock(&z->lk);
+ return -1;
+}