summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/bsd/socket.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/bsd/socket.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/bsd/socket.c')
-rwxr-xr-xsys/src/ape/lib/bsd/socket.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/sys/src/ape/lib/bsd/socket.c b/sys/src/ape/lib/bsd/socket.c
new file mode 100755
index 000000000..6623936b8
--- /dev/null
+++ b/sys/src/ape/lib/bsd/socket.c
@@ -0,0 +1,175 @@
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+#include "priv.h"
+
+Rock *_sock_rock;
+
+Rock*
+_sock_findrock(int fd, struct stat *dp)
+{
+ Rock *r;
+ struct stat d;
+
+ if(dp == 0)
+ dp = &d;
+ fstat(fd, dp);
+ for(r = _sock_rock; r; r = r->next){
+ if(r->inode == dp->st_ino
+ && r->dev == dp->st_dev)
+ break;
+ }
+ return r;
+}
+
+Rock*
+_sock_newrock(int fd)
+{
+ Rock *r;
+ struct stat d;
+
+ r = _sock_findrock(fd, &d);
+ if(r == 0){
+ r = malloc(sizeof(Rock));
+ if(r == 0)
+ return 0;
+ r->dev = d.st_dev;
+ r->inode = d.st_ino;
+ r->other = -1;
+ r->next = _sock_rock;
+ _sock_rock = r;
+ }
+ memset(&r->raddr, 0, sizeof(r->raddr));
+ memset(&r->addr, 0, sizeof(r->addr));
+ r->reserved = 0;
+ r->dev = d.st_dev;
+ r->inode = d.st_ino;
+ r->other = -1;
+ return r;
+}
+
+int
+_sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp)
+{
+ int n, fd;
+ Rock *r;
+ char name[Ctlsize];
+
+ /* get the data file name */
+ n = read(cfd, name, sizeof(name)-1);
+ if(n < 0){
+ close(cfd);
+ errno = ENOBUFS;
+ return -1;
+ }
+ name[n] = 0;
+ n = strtoul(name, 0, 0);
+ snprintf(name, sizeof name, "/net/%s/%d/data", net, n);
+
+ /* open data file */
+ fd = open(name, O_RDWR);
+ close(cfd);
+ if(fd < 0){
+ close(cfd);
+ errno = ENOBUFS;
+ return -1;
+ }
+
+ /* hide stuff under the rock */
+ snprintf(name, sizeof name, "/net/%s/%d/ctl", net, n);
+ r = _sock_newrock(fd);
+ if(r == 0){
+ errno = ENOBUFS;
+ close(fd);
+ return -1;
+ }
+ if(rp)
+ *rp = r;
+ memset(&r->raddr, 0, sizeof(r->raddr));
+ memset(&r->addr, 0, sizeof(r->addr));
+ r->domain = domain;
+ r->stype = stype;
+ r->protocol = protocol;
+ strcpy(r->ctl, name);
+ return fd;
+}
+
+int
+socket(int domain, int stype, int protocol)
+{
+ Rock *r;
+ int cfd, fd, n;
+ int pfd[2];
+ char *net;
+
+ switch(domain){
+ case PF_INET:
+ /* get a free network directory */
+ switch(stype){
+ case SOCK_DGRAM:
+ net = "udp";
+ cfd = open("/net/udp/clone", O_RDWR);
+ break;
+ case SOCK_STREAM:
+ net = "tcp";
+ cfd = open("/net/tcp/clone", O_RDWR);
+ break;
+ default:
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+ if(cfd < 0){
+ _syserrno();
+ return -1;
+ }
+ return _sock_data(cfd, net, domain, stype, protocol, 0);
+ case PF_UNIX:
+ if(pipe(pfd) < 0){
+ _syserrno();
+ return -1;
+ }
+ r = _sock_newrock(pfd[0]);
+ r->domain = domain;
+ r->stype = stype;
+ r->protocol = protocol;
+ r->other = pfd[1];
+ return pfd[0];
+ default:
+ errno = EPROTONOSUPPORT;
+ return -1;
+ }
+}
+
+int
+issocket(int fd)
+{
+ Rock *r;
+
+ r = _sock_findrock(fd, 0);
+ return (r != 0);
+}
+
+/*
+ * probably should do better than this
+ */
+int getsockopt(int, int, int, void *, int *)
+{
+ return -1;
+}
+
+int setsockopt(int, int, int, void *, int)
+{
+ return 0;
+}
+