#include #include #include #include #include #include #include #include <9p.h> #include #include #include "dat.h" #include "fns.h" static int tlsdial(char*, char*, char*, int*, int); static long t(Ioproc *io, void (*op)(Ioproc*), int n, ...) { int i, ret; va_list arg; assert(!io->inuse); io->inuse = 1; io->op = op; va_start(arg, n); for(i=0; iarg[i] = va_arg(arg, long); sendp(io->c, io); recvp(io->c); ret = io->ret; if(ret < 0) errstr(io->err, sizeof io->err); io->inuse = 0; return ret; } static void t2(Ioproc *io, int ret) { io->ret = ret; if(ret < 0) rerrstr(io->err, sizeof io->err); sendp(io->c, io); } static void ioread2(Ioproc*); static long ioread(Ioproc *io, int fd, void *a, long n) { return t(io, ioread2, 3, fd, a, n); } static void ioread2(Ioproc *io) { t2(io, read(io->arg[0], (void*)io->arg[1], io->arg[2])); } static void iowrite2(Ioproc*); static long iowrite(Ioproc *io, int fd, void *a, long n) { return t(io, iowrite2, 3, fd, a, n); } static void iowrite2(Ioproc *io) { t2(io, write(io->arg[0], (void*)io->arg[1], io->arg[2])); } static void ioclose2(Ioproc*); static int ioclose(Ioproc *io, int fd) { return t(io, ioclose2, 1, fd); } static void ioclose2(Ioproc *io) { t2(io, close(io->arg[0])); } static void iodial2(Ioproc*); static int iodial(Ioproc *io, char *a, char *b, char *c, int *d, int e) { return t(io, iodial2, 5, a, b, c, d, e); } static void iodial2(Ioproc *io) { t2(io, tlsdial((char*)io->arg[0], (char*)io->arg[1], (char*)io->arg[2], (int*)io->arg[3], io->arg[4])); } static void ioopen2(Ioproc*); static int ioopen(Ioproc *io, char *path, int mode) { return t(io, ioopen2, 2, path, mode); } static void ioopen2(Ioproc *io) { t2(io, open((char*)io->arg[0], io->arg[1])); } static int ioprint(Ioproc *io, int fd, char *fmt, ...) { char buf[1024]; va_list arg; va_start(arg, fmt); vseprint(buf, buf+sizeof buf, fmt, arg); va_end(arg); return iowrite(io, fd, buf, strlen(buf)); } static void iointerrupt(Ioproc *io) { if(!io->inuse) return; postnote(PNPROC, io->pid, "interrupt"); } static void xioproc(void *a) { Ioproc *io; io = a; io->pid = getpid(); sendp(io->c, nil); while(recvp(io->c) == io) io->op(io); chanfree(io->c); free(io); } static int tlsdial(char *a, char *b, char *c, int *d, int usetls) { int fd, tfd; TLSconn conn; fd = dial(a, b, c, d); if(fd < 0) return -1; if(usetls == 0) return fd; memset(&conn, 0, sizeof conn); tfd = tlsClient(fd, &conn); if(tfd < 0){ print("tls %r\n"); close(fd); return -1; } /* BUG: check cert here? */ if(conn.cert) free(conn.cert); close(fd); return tfd; } Ioproc iofns = { ioread, iowrite, iodial, ioclose, ioopen, ioprint, iointerrupt, }; Ioproc *iofree; Ioproc* ioproc(void) { Ioproc *io; if((io = iofree) != nil){ iofree = io->next; return io; } io = emalloc(sizeof(*io)); *io = iofns; io->c = chancreate(sizeof(void*), 0); if(proccreate(xioproc, io, STACK) < 0) sysfatal("proccreate: %r"); recvp(io->c); return io; } void closeioproc(Ioproc *io) { io->next = iofree; iofree = io; }