int so_accept(int fd, uchar *raddr, ushort *rport) { int nfd; socklen_t len; struct sockaddr sa; struct sockaddr_in *sin; sin = (struct sockaddr_in*)&sa; len = sizeof(sa); osenter(); if(doselect(fd) < 0) { osleave(); return -1; } nfd = accept(fd, &sa, &len); osleave(); if(nfd < 0) oserror(); if(sin->sin_family != AF_INET || len != sizeof(*sin)) error(Enotv4); ipw6(raddr, sin->sin_addr.s_addr); *rport = nhgets(&sin->sin_port); return nfd; }
static long fsdirread(Chan *c, void *va, long count, vlong offset) { long n, r; static char slop[16384]; if(FS(c)->offset != offset){ seek(FS(c)->fd, 0, 0); for(n=0; n<offset;) { r = offset - n; if(r > sizeof(slop)) r = sizeof(slop); osenter(); r = read(FS(c)->fd, slop, r); osleave(); if(r <= 0){ FS(c)->offset = n; return 0; } n += r; } FS(c)->offset = offset; } osenter(); r = read(FS(c)->fd, va, count); osleave(); if(r < 0) return r; FS(c)->offset = offset+r; return r; }
int so_accept(int fd, unsigned long *raddr, unsigned short *rport) { int nfd, len; struct sockaddr sa; struct sockaddr_in *sin; sin = (struct sockaddr_in*)&sa; len = sizeof(sa); osenter(); if(doselect(fd) < 0) { osleave(); return -1; } nfd = accept(fd, &sa, &len); osleave(); if(nfd < 0) oserror(); if(sin->sin_family != AF_INET || len != sizeof(*sin)) error("not AF_INET"); *raddr = nhgetl(&sin->sin_addr.s_addr); *rport = nhgets(&sin->sin_port); return nfd; }
int so_recv(int sock, void *va, int len, void *hdr, int hdrlen) { int r, l; struct sockaddr sa; struct sockaddr_in *sin; char h[Udphdrlen]; osenter(); if(doselect(sock) < 0) { osleave(); return -1; } if(hdr == 0) r = recv(sock, va, len, 0); else { sin = (struct sockaddr_in*)&sa; l = sizeof(sa); r = recvfrom(sock, va, len, 0, &sa, &l); if(r >= 0) { memset(h, sizeof h, 0); switch(hdrlen){ case OUdphdrlenv4: memmove(h, &sin->sin_addr, 4); memmove(h+2*IPv4addrlen, &sin->sin_port, 2); break; case OUdphdrlen: v4tov6(h, (uchar*)&sin->sin_addr); memmove(h+2*IPaddrlen, &sin->sin_port, 2); break; default: v4tov6(h, (uchar*)&sin->sin_addr); memmove(h+3*IPaddrlen, &sin->sin_port, 2); break; } /* alas there's no way to get the local addr/port correctly. Pretend. */ getsockname(sock, &sa, &l); switch(hdrlen){ case OUdphdrlenv4: memmove(h+IPv4addrlen, &sin->sin_addr, IPv4addrlen); memmove(h+2*IPv4addrlen+2, &sin->sin_port, 2); break; case OUdphdrlen: v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); memmove(h+2*IPaddrlen+2, &sin->sin_port, 2); break; default: v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); v4tov6(h+2*IPaddrlen, (uchar*)&sin->sin_addr); /* ifcaddr */ memmove(h+3*IPaddrlen+2, &sin->sin_port, 2); break; } memmove(hdr, h, hdrlen); } } osleave(); return r; }
static Chan* eiaopen(Chan *c, int mode) { int port = NETID(c->qid.path); struct termios ts; int r; c = devopen(c, mode, eiadir, ndir, devgen); switch(NETTYPE(c->qid.path)) { case Nctlqid: case Ndataqid: case Nstatqid: if(incref(&eia[port].r) != 1) break; osenter(); eia[port].fd = open(sysdev[port], O_RDWR); osleave(); if(eia[port].fd < 0) oserror(); /* make port settings sane */ if(tcgetattr(eia[port].fd, &ts) < 0) oserror(); ts.c_iflag = ts.c_oflag = ts.c_lflag = 0; if(eia[port].restore) ts = eia[port].ts; else { cfsetispeed(&ts, B9600); cfsetospeed(&ts, B9600); ts.c_iflag |= IGNPAR; ts.c_cflag &= ~CSIZE; ts.c_cflag |= CS8|CREAD; ts.c_cflag &= ~(PARENB|PARODD); ts.c_cc[VMIN] = 1; ts.c_cc[VTIME] = 0; } osenter(); r = tcsetattr(eia[port].fd, TCSANOW, &ts); osleave(); if(r < 0) oserror(); if(eia[port].restore) resxtra(port, &ts); break; } return c; }
static long eiawrite(Chan *c, void *buf, long n, vlong offset) { ssize_t cnt; char cmd[Maxctl]; int port = NETID(c->qid.path); USED(offset); if(c->qid.type & QTDIR) error(Eperm); switch(NETTYPE(c->qid.path)) { case Ndataqid: osenter(); cnt = write(eia[port].fd, buf, n); osleave(); if(cnt == -1) oserror(); return cnt; case Nctlqid: if(n >= (long)sizeof(cmd)) n = sizeof(cmd)-1; memmove(cmd, buf, n); cmd[n] = 0; wrctl(port, cmd); return n; } return 0; }
void fscreate(Chan *c, char *name, int mode, ulong perm) { Dir *d; Cname *n; if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) error(Efilename); n = addelem(newcname(FS(c)->name->s), name); osenter(); FS(c)->fd = create(n->s, mode, perm); osleave(); if(FS(c)->fd < 0) { cnameclose(n); fserr(FS(c)); } d = dirfstat(FS(c)->fd); if(d == nil) { cnameclose(n); close(FS(c)->fd); FS(c)->fd = -1; fserr(FS(c)); } c->qid = d->qid; free(d); cnameclose(FS(c)->name); FS(c)->name = n; c->mode = openmode(mode); c->offset = 0; FS(c)->offset = 0; c->flag |= COPEN; }
static long eiaread(Chan *c, void *buf, long n, vlong offset) { ssize_t cnt; int port = NETID(c->qid.path); if(c->qid.type & QTDIR) return devdirread(c, buf, n, eiadir, ndir, devgen); switch(NETTYPE(c->qid.path)) { case Ndataqid: osenter(); cnt = read(eia[port].fd, buf, n); osleave(); if(cnt == -1) oserror(); return cnt; case Nctlqid: return readnum(offset, buf, n, port, NUMSIZE); case Nstatqid: return rdstat(port, buf, n, offset); } return 0; }
int so_send(int sock, void *va, int len, void *hdr, int hdrlen) { int r; struct sockaddr_storage sa; struct sockaddr_in6 *sin6; char *h = hdr; osenter(); if(hdr == 0) r = write(sock, va, len); else { memset(&sa, 0, sizeof(sa)); sin6 = (struct sockaddr_in6*)&sa; sin6->sin6_family = AF_INET6; switch(hdrlen){ case OUdphdrlenv4: v4tov6((uchar*)&sin6->sin6_addr, h); memmove(&sin6->sin6_port, h+8, 2); break; case OUdphdrlen: memmove((uchar*)&sin6->sin6_addr, h, IPaddrlen); memmove(&sin6->sin6_port, h+2*IPaddrlen, 2); /* rport */ break; default: memmove((uchar*)&sin6->sin6_addr, h, IPaddrlen); memmove(&sin6->sin6_port, h+3*IPaddrlen, 2); break; } r = sendto(sock, va, len, 0, (struct sockaddr*)sin6, sizeof(*sin6)); } osleave(); return r; }
int so_send(int sock, void *va, int len, void *hdr, int hdrlen) { int r; struct sockaddr sa; struct sockaddr_in *sin; uchar *h = hdr; osenter(); if(hdr == 0) r = send(sock, va, len, 0); else { memset(&sa, 0, sizeof(sa)); sin = (struct sockaddr_in*)&sa; sin->sin_family = AF_INET; switch(hdrlen){ case OUdphdrlenv4: memmove(&sin->sin_addr, h, 4); memmove(&sin->sin_port, h+8, 2); break; case OUdphdrlen: v6tov4((uchar*)&sin->sin_addr, h); memmove(&sin->sin_port, h+2*IPaddrlen, 2); /* rport */ break; default: v6tov4((uchar*)&sin->sin_addr, h); memmove(&sin->sin_port, h+3*IPaddrlen, 2); break; } r = sendto(sock, va, len, 0, &sa, sizeof(sa)); } osleave(); return r; }
static long eiaread(Chan *c, void *buf, long n, vlong offset) { DWORD cnt; int port = NETID(c->qid.path); BOOL good; if(c->qid.type & QTDIR) return devdirread(c, buf, n, eiadir, ndir, devgen); switch(NETTYPE(c->qid.path)) { case Ndataqid: cnt = 0; // if ReadFile timeouts and cnt==0 then just re-read // this will give osleave() a chance to detect an // interruption (i.e. killprog) while(cnt==0) { osenter(); good = ReadFile(eia[port].comfh, buf, n, &cnt, NULL); SleepEx(0,FALSE); //allow another thread access to port osleave(); if(!good) oserror(); } return cnt; case Nctlqid: return readnum(offset, buf, n, eia[port].id, NUMSIZE); case Nstatqid: return rdstat(port, buf, n, offset); } return 0; }
static void cmdproc(void *a) { Conv *c; int n; char status[ERRMAX]; void *t; c = a; qlock(&c->l); if(Debug) print("f[0]=%q f[1]=%q\n", c->cmd->f[0], c->cmd->f[1]); if(waserror()){ if(Debug) print("failed: %q\n", up->env->errstr); kstrdup(&c->error, up->env->errstr); c->state = "Done"; qunlock(&c->l); Wakeup(&c->startr); pexit("cmdproc", 0); } t = oscmd(c->cmd->f+1, c->nice, c->dir, c->fd); if(t == nil) oserror(); c->child = t; /* to allow oscmdkill */ poperror(); qunlock(&c->l); Wakeup(&c->startr); if(Debug) print("started\n"); while(waserror()) oscmdkill(t); osenter(); n = oscmdwait(t, status, sizeof(status)); osleave(); if(n < 0){ oserrstr(up->genbuf, sizeof(up->genbuf)); n = snprint(status, sizeof(status), "0 0 0 0 %q", up->genbuf); } qlock(&c->l); c->child = nil; oscmdfree(t); if(Debug){ status[n]=0; print("done %d %d %d: %q\n", c->fd[0], c->fd[1], c->fd[2], status); } if(c->inuse > 0){ c->state = "Done"; if(c->waitq != nil) qproduce(c->waitq, status, n); }else closeconv(c); qunlock(&c->l); pexit("", 0); }
void fsclose(Chan *c) { if(c->flag & COPEN){ osenter(); close(FS(c)->fd); osleave(); } /* don't need to check for CRCLOSE, because Plan 9 itself implements ORCLOSE */ fsfree(c); }
void so_listen(int fd) { int r; osenter(); r = listen(fd, 256); osleave(); if(r < 0) oserror(); }
long fswrite(Chan *c, void *va, long n, vlong offset) { int r; osenter(); r = pwrite(FS(c)->fd, va, n, offset); osleave(); if(r < 0) fserr(FS(c)); return r; }
int fswstat(Chan *c, uchar *dp, int n) { osenter(); if(FS(c)->fd >= 0) n = fwstat(FS(c)->fd, dp, n); else n = wstat(FS(c)->name->s, dp, n); osleave(); if(n < 0) fserr(FS(c)); return n; }
int so_hangup(int fd, int nolinger) { int r; static struct linger l = {1, 0}; osenter(); if(nolinger) setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l)); r = closesocket(fd); osleave(); return r; }
static long cmdread(Chan *ch, void *a, long n, vlong offset) { Conv *c; char *p, *cmds; int fd; USED(offset); p = a; switch(TYPE(ch->qid)) { default: error(Eperm); case Qcmd: case Qtopdir: case Qconvdir: return devdirread(ch, a, n, 0, 0, cmdgen); case Qctl: sprint(up->genbuf, "%ld", CONV(ch->qid)); return readstr(offset, p, n, up->genbuf); case Qstatus: c = cmd.conv[CONV(ch->qid)]; cmds = ""; if(c->cmd != nil) cmds = c->cmd->f[1]; snprint(up->genbuf, sizeof(up->genbuf), "cmd/%d %d %s %q %q\n", c->x, c->inuse, c->state, c->dir, cmds); return readstr(offset, p, n, up->genbuf); case Qdata: case Qstderr: fd = 1; if(TYPE(ch->qid) == Qstderr) fd = 2; c = cmd.conv[CONV(ch->qid)]; qlock(&c->l); if(c->fd[fd] == -1){ qunlock(&c->l); return 0; } qunlock(&c->l); osenter(); n = read(c->fd[fd], a, n); osleave(); if(n < 0) oserror(); return n; case Qwait: c = cmd.conv[CONV(ch->qid)]; return qread(c->waitq, a, n); } }
Chan* fsopen(Chan *c, int mode) { osenter(); FS(c)->fd = open(FS(c)->name->s, mode); osleave(); if(FS(c)->fd < 0) fserr(FS(c)); c->mode = openmode(mode); c->offset = 0; FS(c)->offset = 0; c->flag |= COPEN; return c; }
void so_setsockopt(int fd, int opt, int value) { int r; struct linger l; if(opt == SO_LINGER){ l.l_onoff = 1; l.l_linger = (short) value; osenter(); r = setsockopt(fd, SOL_SOCKET, opt, (char *)&l, sizeof(l)); osleave(); }else error(Ebadctl); if(r < 0) oserror(); }
void fsremove(Chan *c) { int r; if(waserror()){ fsfree(c); nexterror(); } osenter(); r = remove(FS(c)->name->s); osleave(); if(r < 0) fserr(FS(c)); poperror(); fsfree(c); }
void so_connect(int fd, uchar *raddr, ushort rport) { int r; struct sockaddr_storage sa; struct sockaddr_in6 *sin6; memset(&sa, 0, sizeof(sa)); sin6 = (struct sockaddr_in6*)&sa; sin6->sin6_family = AF_INET6; hnputs(&sin6->sin6_port, rport); memmove((uchar*)&sin6->sin6_addr, raddr, IPaddrlen); osenter(); r = connect(fd, (struct sockaddr*)sin6, sizeof(*sin6)); osleave(); if(r < 0) oserror(); }
void so_connect(int fd, unsigned long raddr, unsigned short rport) { int r; struct sockaddr sa; struct sockaddr_in *sin; memset(&sa, 0, sizeof(sa)); sin = (struct sockaddr_in*)&sa; sin->sin_family = AF_INET; hnputs(&sin->sin_port, rport); hnputl(&sin->sin_addr.s_addr, raddr); osenter(); r = connect(fd, &sa, sizeof(sa)); osleave(); if(r < 0) oserror(); }
static void eiaclose(Chan *c) { int port = NETID(c->qid.path); if((c->flag & COPEN) == 0) return; switch(NETTYPE(c->qid.path)) { case Nctlqid: case Ndataqid: case Nstatqid: if(decref(&eia[port].r) == 0) { osenter(); CloseHandle(eia[port].comfh); osleave(); } break; } }
void so_connect(int fd, uchar *raddr, ushort rport) { int r; struct sockaddr sa; struct sockaddr_in *sin; if(!isv4(raddr)) error(Enotv4); memset(&sa, 0, sizeof(sa)); sin = (struct sockaddr_in*)&sa; sin->sin_family = AF_INET; hnputs(&sin->sin_port, rport); memmove(&sin->sin_addr.s_addr, raddr+IPv4off, IPv4addrlen); osenter(); r = connect(fd, &sa, sizeof(sa)); osleave(); if(r < 0) oserror(); }
static long eiawrite(Chan *c, void *buf, long n, vlong offset) { DWORD cnt; char cmd[Maxctl]; int port = NETID(c->qid.path); BOOL good; uchar *data; if(c->qid.type & QTDIR) error(Eperm); switch(NETTYPE(c->qid.path)) { case Ndataqid: cnt = 0; data = (uchar*)buf; // if WriteFile times out (i.e. return true; cnt<n) then // allow osleave() to check for an interrupt otherwise try // to send the unsent data. while(n>0) { osenter(); good = WriteFile(eia[port].comfh, data, n, &cnt, NULL); osleave(); if(!good) oserror(); data += cnt; n -= cnt; } return (data-(uchar*)buf); case Nctlqid: if(n >= sizeof(cmd)) n = sizeof(cmd)-1; memmove(cmd, buf, n); cmd[n] = 0; wrctl(port, cmd); return n; } return 0; }
int so_accept(int fd, uchar *raddr, ushort *rport) { int nfd, len; struct sockaddr_storage sa; struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6*)&sa; len = sizeof(*sin6); osenter(); nfd = accept(fd, (struct sockaddr*)&sa, &len); osleave(); if(nfd < 0) oserror(); if(sin6->sin6_family != AF_INET6 || len != sizeof(*sin6)) error("not AF_INET6"); memmove(raddr, &sin6->sin6_addr, IPaddrlen); *rport = nhgets(&sin6->sin6_port); return nfd; }
long fsread(Chan *c, void *va, long n, vlong offset) { int r; if(c->qid.type & QTDIR){ /* need to maintain offset only for directories */ qlock(FS(c)); if(waserror()){ qunlock(FS(c)); nexterror(); } r = fsdirread(c, va, n, offset); poperror(); qunlock(FS(c)); }else{ osenter(); r = pread(FS(c)->fd, va, n, offset); osleave(); } if(r < 0) fserr(FS(c)); return r; }
static long cmdwrite(Chan *ch, void *a, long n, vlong offset) { int i, r; Conv *c; Cmdbuf *cb; Cmdtab *ct; USED(offset); switch(TYPE(ch->qid)) { default: error(Eperm); case Qctl: c = cmd.conv[CONV(ch->qid)]; cb = parsecmd(a, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, cmdtab, nelem(cmdtab)); switch(ct->index){ case CMdir: kstrdup(&c->dir, cb->f[1]); break; case CMexec: poperror(); /* cb */ qlock(&c->l); if(waserror()){ qunlock(&c->l); free(cb); nexterror(); } if(c->child != nil || c->cmd != nil) error(Einuse); for(i = 0; i < nelem(c->fd); i++) if(c->fd[i] != -1) error(Einuse); if(cb->nf < 1) error(Etoosmall); kproc("cmdproc", cmdproc, c, 0); /* cmdproc held back until unlock below */ free(c->cmd); c->cmd = cb; /* don't free cb */ c->state = "Execute"; poperror(); qunlock(&c->l); while(waserror()) ; Sleep(&c->startr, cmdstarted, c); poperror(); if(c->error) error(c->error); return n; /* avoid free(cb) below */ case CMkill: qlock(&c->l); if(waserror()){ qunlock(&c->l); nexterror(); } if(c->child == nil) error("not started"); if(oscmdkill(c->child) < 0) oserror(); poperror(); qunlock(&c->l); break; case CMnice: c->nice = cb->nf > 1? atoi(cb->f[1]): 1; break; case CMkillonclose: c->killonclose = 1; break; } poperror(); free(cb); break; case Qdata: c = cmd.conv[CONV(ch->qid)]; qlock(&c->l); if(c->fd[0] == -1){ qunlock(&c->l); error(Ehungup); } qunlock(&c->l); osenter(); r = write(c->fd[0], a, n); osleave(); if(r == 0) error(Ehungup); if(r < 0) { /* XXX perhaps should kill writer "write on closed pipe" here, 2nd time around? */ oserror(); } return r; } return n; }
int so_recv(int sock, void *va, int len, void *hdr, int hdrlen) { int r, l; struct sockaddr_storage sa; struct sockaddr_in6 *sin6; char h[Udphdrlen]; osenter(); if(hdr == 0) r = read(sock, va, len); else { sin6 = (struct sockaddr_in6*)&sa; l = sizeof(sa); r = recvfrom(sock, va, len, 0, (struct sockaddr*)&sa, &l); if(r >= 0) { memset(h, 0, sizeof(h)); switch(hdrlen){ case OUdphdrlenv4: if(v6tov4(h, (uchar*)&sin6->sin6_addr) < 0) { osleave(); error("OUdphdrlenv4 with IPv6 address"); } memmove(h+2*IPv4addrlen, &sin6->sin6_port, 2); break; case OUdphdrlen: memmove(h, (uchar*)&sin6->sin6_addr, IPaddrlen); memmove(h+2*IPaddrlen, &sin6->sin6_port, 2); break; default: memmove(h, (uchar*)&sin6->sin6_addr, IPaddrlen); memmove(h+3*IPaddrlen, &sin6->sin6_port, 2); break; } /* alas there's no way to get the local addr/port correctly. Pretend. */ memset(&sa, 0, sizeof(sa)); l = sizeof(sa); getsockname(sock, (struct sockaddr*)&sa, &l); switch(hdrlen){ case OUdphdrlenv4: /* * we get v6Unspecified/noaddr if local address cannot be determined. * that's reasonable for ipv4 too. */ if(ipcmp(v6Unspecified, (uchar*)&sin6->sin6_addr) != 0 && v6tov4(h+IPv4addrlen, (uchar*)&sin6->sin6_addr) < 0) { osleave(); error("OUdphdrlenv4 with IPv6 address"); } memmove(h+2*IPv4addrlen+2, &sin6->sin6_port, 2); break; case OUdphdrlen: memmove(h+IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen); memmove(h+2*IPaddrlen+2, &sin6->sin6_port, 2); break; default: memmove(h+IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen); memmove(h+2*IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen); /* ifcaddr */ memmove(h+3*IPaddrlen+2, &sin6->sin6_port, 2); break; } memmove(hdr, h, hdrlen); } } osleave(); return r; }