| /* Copyright (c) 2004 Russ Cox */ |
| #include <u.h> |
| #include <libc.h> |
| #include <venti.h> |
| #include <thread.h> |
| #include <libsec.h> |
| |
| #ifndef _UNISTD_H_ |
| #pragma varargck type "F" VtFcall* |
| #pragma varargck type "T" void |
| #endif |
| |
| VtConn *z; |
| int verbose; |
| |
| enum |
| { |
| STACK = 8192 |
| }; |
| |
| void |
| usage(void) |
| { |
| fprint(2, "usage: venti/ro [-v] [-a address] [-h address]\n"); |
| threadexitsall("usage"); |
| } |
| |
| void |
| readthread(void *v) |
| { |
| char err[ERRMAX]; |
| VtReq *r; |
| uchar *buf; |
| int n; |
| |
| r = v; |
| buf = vtmalloc(r->tx.count); |
| if((n=vtread(z, r->tx.score, r->tx.blocktype, buf, r->tx.count)) < 0){ |
| r->rx.msgtype = VtRerror; |
| rerrstr(err, sizeof err); |
| r->rx.error = vtstrdup(err); |
| free(buf); |
| }else{ |
| r->rx.data = packetforeign(buf, n, free, buf); |
| } |
| if(verbose) |
| fprint(2, "-> %F\n", &r->rx); |
| vtrespond(r); |
| } |
| |
| void |
| threadmain(int argc, char **argv) |
| { |
| VtReq *r; |
| VtSrv *srv; |
| char *address, *ventiaddress; |
| |
| fmtinstall('F', vtfcallfmt); |
| fmtinstall('V', vtscorefmt); |
| |
| address = "tcp!*!venti"; |
| ventiaddress = nil; |
| |
| ARGBEGIN{ |
| case 'v': |
| verbose++; |
| break; |
| case 'a': |
| address = EARGF(usage()); |
| break; |
| case 'h': |
| ventiaddress = EARGF(usage()); |
| break; |
| default: |
| usage(); |
| }ARGEND |
| |
| if((z = vtdial(ventiaddress)) == nil) |
| sysfatal("vtdial %s: %r", ventiaddress); |
| if(vtconnect(z) < 0) |
| sysfatal("vtconnect: %r"); |
| |
| srv = vtlisten(address); |
| if(srv == nil) |
| sysfatal("vtlisten %s: %r", address); |
| |
| while((r = vtgetreq(srv)) != nil){ |
| r->rx.msgtype = r->tx.msgtype+1; |
| if(verbose) |
| fprint(2, "<- %F\n", &r->tx); |
| switch(r->tx.msgtype){ |
| case VtTping: |
| break; |
| case VtTgoodbye: |
| break; |
| case VtTread: |
| threadcreate(readthread, r, 16384); |
| continue; |
| case VtTwrite: |
| r->rx.error = vtstrdup("read-only server"); |
| r->rx.msgtype = VtRerror; |
| break; |
| case VtTsync: |
| break; |
| } |
| if(verbose) |
| fprint(2, "-> %F\n", &r->rx); |
| vtrespond(r); |
| } |
| threadexitsall(nil); |
| } |
| |