Re-add the bsd library
authorRonald G. Minnich <rminnich@google.com>
Fri, 25 Apr 2014 21:09:41 +0000 (14:09 -0700)
committerRonald G. Minnich <rminnich@google.com>
Fri, 25 Apr 2014 21:09:41 +0000 (14:09 -0700)
We need it for netperf. I'm not in the mood to try to change
an autoconfig-based chamber of horrors at this point in my life.
Far easier to make a compatibility shim, and that alone should tell
you all you need to know about what's wrong with open source software
nowadays.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
28 files changed:
user/bsd/Makefile [new file with mode: 0644]
user/bsd/_sock_ingetaddr.c [new file with mode: 0644]
user/bsd/_sock_ipattr.c [new file with mode: 0644]
user/bsd/_sock_srv.c [new file with mode: 0644]
user/bsd/accept.c [new file with mode: 0644]
user/bsd/bind.c [new file with mode: 0644]
user/bsd/connect.c [new file with mode: 0644]
user/bsd/gethostbyaddr.c [new file with mode: 0644]
user/bsd/gethostbyname.c [new file with mode: 0644]
user/bsd/gethostname.c [new file with mode: 0644]
user/bsd/getpeername.c [new file with mode: 0644]
user/bsd/getprotobyname.c [new file with mode: 0644]
user/bsd/getservbyaddr.c [new file with mode: 0644]
user/bsd/getservbyname.c [new file with mode: 0644]
user/bsd/getsockname.c [new file with mode: 0644]
user/bsd/inet_addr.c [new file with mode: 0644]
user/bsd/inet_ntoa.c [new file with mode: 0644]
user/bsd/listen.c [new file with mode: 0644]
user/bsd/nptohl.c [new file with mode: 0644]
user/bsd/ntohl.c [new file with mode: 0644]
user/bsd/priv.h [new file with mode: 0644]
user/bsd/putenv.c [new file with mode: 0644]
user/bsd/rresvport.c [new file with mode: 0644]
user/bsd/send.c [new file with mode: 0644]
user/bsd/sendto.c [new file with mode: 0644]
user/bsd/shutdown.c [new file with mode: 0644]
user/bsd/socket.c [new file with mode: 0644]
user/bsd/socketpair.c [new file with mode: 0644]

diff --git a/user/bsd/Makefile b/user/bsd/Makefile
new file mode 100644 (file)
index 0000000..66470b6
--- /dev/null
@@ -0,0 +1,47 @@
+ARCH ?= none   # catch bugs
+CFLAGS_USER += -static -fomit-frame-pointer -g
+LIBNAME = bsd
+
+SRCDIR := 
+OBJDIR := $(SRCDIR)obj
+INCDIR = .
+
+INCS = -I. -I$(INCDIR)
+FINALLIB = $(OBJDIR)/lib$(LIBNAME).a
+
+uc = $(shell echo $(1) | tr a-z A-Z)
+
+LIBUCNAME := $(call uc, $(LIBNAME))
+HEADERS := $(shell find $(INCDIR) -name *.h)
+CFILES  := $(wildcard $(SRCDIR)*.c)
+CFILES  += $(wildcard $(SRCDIR)$(ARCH)/*.c)
+SFILES  := $(wildcard $(SRCDIR)$(ARCH)/*.S)
+OBJS    := $(patsubst %.c, $(OBJDIR)/%.o, $(CFILES)) \
+           $(patsubst %.S, $(OBJDIR)/%.o, $(SFILES))
+
+all: $(FINALLIB)
+       @:
+
+$(OBJDIR)/$(ARCH)/%.o: $(SRCDIR)$(ARCH)/%.S $(HEADERS)
+       @echo + as [$(LIBUCNAME)] $<
+       @mkdir -p $(@D)
+       $(Q)$(CC) $(CFLAGS_USER) $(INCS) -o $@ -c $<
+
+$(OBJDIR)/%.o: $(SRCDIR)%.c $(HEADERS)
+       @echo + cc [$(LIBUCNAME)] $<
+       @mkdir -p $(@D)
+       $(Q)$(CC) $(CFLAGS_USER) $(INCS) -o $@ -c $<
+
+$(FINALLIB): $(OBJS)
+       @echo + ar [$(LIBUCNAME)] $@
+       @mkdir -p $(@D)
+       $(Q)$(AR) rc $@ $(OBJS)
+
+install: $(FINALLIB)
+       @cp $(FINALLIB) $(XCC_TARGET_ROOT)/lib/
+
+clean: 
+       @echo + clean [$(LIBUCNAME)]
+       $(Q)rm -rf $(FINALLIB)
+       $(Q)rm -rf $(OBJDIR)
+
diff --git a/user/bsd/_sock_ingetaddr.c b/user/bsd/_sock_ingetaddr.c
new file mode 100644 (file)
index 0000000..1f68681
--- /dev/null
@@ -0,0 +1,56 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+
+#include "priv.h"
+
+void
+_sock_ingetaddr(Rock *r, struct sockaddr_in *ip, int *alen, char *a)
+{
+       int n, fd;
+       char *p;
+       char name[Ctlsize];
+
+       /* get remote address */
+       strcpy(name, r->ctl);
+       p = strrchr(name, '/');
+       strcpy(p+1, a);
+       fd = open(name, O_RDONLY);
+       if(fd >= 0){
+               n = read(fd, name, sizeof(name)-1);
+               if(n > 0){
+                       name[n] = 0;
+                       p = strchr(name, '!');
+                       if(p){
+                               *p++ = 0;
+                               ip->sin_family = AF_INET;
+                               ip->sin_port = atoi(p);
+                               ip->sin_addr.s_addr = inet_addr(name);
+                               if(alen)
+                                       *alen = sizeof(struct sockaddr_in);
+                       }
+               }
+               close(fd);
+       }
+
+}
diff --git a/user/bsd/_sock_ipattr.c b/user/bsd/_sock_ipattr.c
new file mode 100644 (file)
index 0000000..dc9675d
--- /dev/null
@@ -0,0 +1,54 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "priv.h"
+
+/*
+ *  return ndb attribute type of an ip name
+ */
+int
+_sock_ipattr(const char *name)
+{
+       const char *p;
+       int dot = 0;
+       int alpha = 0;
+
+       for(p = name; *p; p++){
+               if(isdigit(*p))
+                       ;
+               else if(isalpha(*p) || *p == '-')
+                       alpha = 1;
+               else if(*p == '.')
+                       dot = 1;
+               else
+                       return Tsys;
+       }
+
+       if(alpha){
+               if(dot)
+                       return Tdom;
+               else
+                       return Tsys;
+       }
+
+       if(dot)
+               return Tip;
+       else
+               return Tsys;
+}
diff --git a/user/bsd/_sock_srv.c b/user/bsd/_sock_srv.c
new file mode 100644 (file)
index 0000000..2acd025
--- /dev/null
@@ -0,0 +1,69 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* socket extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "priv.h"
+
+/* we can't avoid overrunning npath because we don't know how big it is. */
+void
+_sock_srvname(char *npath, char *path)
+{
+       char *p;
+
+       strcpy(npath, "/srv/UD.");
+       p = strrchr(path, '/');
+       if(p == 0)
+               p = path;
+       else
+               p++;
+       strcat(npath, p);
+}
+
+int
+_sock_srv(char *path, int fd)
+{
+       int sfd;
+       char msg[8+256+1];
+
+       /* change the path to something in srv */
+       _sock_srvname(msg, path);
+
+       /* remove any previous instance */
+       unlink(msg);
+
+       /* put the fd in /srv and then close it */
+       sfd = creat(msg, 0666);
+       if(sfd < 0){
+               close(fd);
+               _syserrno();
+               return -1;
+       }
+       snprintf(msg, sizeof msg, "%d", fd);
+       if(write(sfd, msg, strlen(msg)) < 0){
+               _syserrno();
+               close(sfd);
+               close(fd);
+               return -1;
+       }
+       close(sfd);
+       close(fd);
+       return 0;
+}
diff --git a/user/bsd/accept.c b/user/bsd/accept.c
new file mode 100644 (file)
index 0000000..fbf3c01
--- /dev/null
@@ -0,0 +1,132 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "priv.h"
+
+/* they've made the delcarations hurl-inducing. */
+int
+accept(int fd, __SOCKADDR_ARG __addr,
+       socklen_t *__restrict alen)
+{
+       void *a = (void*)__addr;
+       int n, nfd, cfd;
+       Rock *r, *nr;
+       struct sockaddr_in *ip;
+       char name[Ctlsize];
+       char file[8+Ctlsize+1];
+       char *p, *net;
+
+       r = _sock_findrock(fd, 0);
+       if(r == 0){
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       switch(r->domain){
+       case PF_INET:
+               switch(r->stype){
+               case SOCK_DGRAM:
+                       net = "udp";
+                       break;
+               case SOCK_STREAM:
+                       net = "tcp";
+                       break;
+               }
+
+               /* get control file name from listener process */
+               n = read(fd, name, sizeof(name)-1);
+               if(n <= 0){
+                       _syserrno();
+                       return -1;
+               }
+               name[n] = 0;
+               cfd = open(name, O_RDWR);
+               if(cfd < 0){
+                       _syserrno();
+                       return -1;
+               }
+
+               nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr);
+               if(nfd < 0){
+                       _syserrno();
+                       return -1;
+               }
+
+               if(write(fd, "OK", 2) < 0){
+                       close(nfd);
+                       _syserrno();
+                       return -1;
+               }
+
+               /* get remote address */
+               ip = (struct sockaddr_in*)&nr->raddr;
+               _sock_ingetaddr(nr, ip, &n, "remote");
+               if(a){
+                       memmove(a, ip, sizeof(struct sockaddr_in));
+                       *alen = sizeof(struct sockaddr_in);
+               }
+
+               return nfd;
+       case PF_UNIX:
+               if(r->other >= 0){
+                       errno = EINVAL; // was EGREG
+                       return -1;
+               }
+
+               for(;;){
+                       /* read path to new connection */
+                       n = read(fd, name, sizeof(name) - 1);
+                       if(n < 0)
+                               return -1;
+                       if(n == 0)
+                               continue;
+                       name[n] = 0;
+
+                       /* open new connection */
+                       _sock_srvname(file, name);
+                       nfd = open(file, O_RDWR);
+                       if(nfd < 0)
+                               continue;
+
+                       /* confirm opening on new connection */
+                       if(write(nfd, name, strlen(name)) > 0)
+                               break;
+
+                       close(nfd);
+               }
+
+               nr = _sock_newrock(nfd);
+               if(nr == 0){
+                       close(nfd);
+                       return -1;
+               }
+               nr->domain = r->domain;
+               nr->stype = r->stype;
+               nr->protocol = r->protocol;
+
+               return nfd;
+       default:
+               errno = EOPNOTSUPP;
+               return -1;
+       }
+}
diff --git a/user/bsd/bind.c b/user/bsd/bind.c
new file mode 100644 (file)
index 0000000..1942df4
--- /dev/null
@@ -0,0 +1,73 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+/* socket extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "priv.h"
+
+int bind (int fd, __CONST_SOCKADDR_ARG a, socklen_t alen)
+{
+       int n, len, cfd;
+       Rock *r;
+       char msg[128];
+       struct sockaddr_in *lip;
+
+       /* assign the address */
+       r = _sock_findrock(fd, 0);
+       if(r == 0){
+               errno = ENOTSOCK;
+               return -1;
+       }
+       if(alen > sizeof(r->addr)){
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       memmove(&r->addr, a, alen);
+
+       /* the rest is IP sepecific */
+       if (r->domain != PF_INET)
+               return 0;
+
+       cfd = open(r->ctl, O_RDWR);
+       if(cfd < 0){
+               errno = EBADF;
+               return -1;
+       }
+       lip = (struct sockaddr_in*)&r->addr;
+       if(lip->sin_port > 0)
+               snprintf(msg, sizeof msg, "bind %d", ntohs(lip->sin_port));
+       else
+               strcpy(msg, "bind *");
+       n = write(cfd, msg, strlen(msg));
+       if(n < 0){
+               errno = EOPNOTSUPP;     /* Improve error reporting!!! */
+               close(cfd);
+               return -1;
+       }
+       close(cfd);
+
+       if(lip->sin_port <= 0)
+               _sock_ingetaddr(r, lip, &len, "local");
+
+       return 0;
+}
diff --git a/user/bsd/connect.c b/user/bsd/connect.c
new file mode 100644 (file)
index 0000000..8b67821
--- /dev/null
@@ -0,0 +1,120 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+
+#include "priv.h"
+
+int connect (int fd, __CONST_SOCKADDR_ARG a, socklen_t alen)
+{
+       Rock *r;
+       int n, cfd, nfd;
+       char msg[8+256+1], file[8+256+1];
+       struct sockaddr_in *lip, *rip;
+       struct sockaddr_un *runix;
+       static int vers;
+
+       r = _sock_findrock(fd, 0);
+       if(r == 0){
+               errno = ENOTSOCK;
+               return -1;
+       }
+       if(alen > sizeof(r->raddr)){
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       memmove(&r->raddr, a, alen);
+
+       switch(r->domain){
+       case PF_INET:
+               /* set up a tcp or udp connection */
+               cfd = open(r->ctl, O_RDWR);
+               if(cfd < 0){
+                       _syserrno();
+                       return -1;
+               }
+               /* whatever .. */
+               rip = (void *)a;
+               lip = (struct sockaddr_in*)&r->addr;
+               if(lip->sin_port)
+                       snprintf(msg, sizeof msg, "connect %s!%d%s %d",
+                               inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
+                               r->reserved ? "!r" : "",
+                               ntohs(lip->sin_port));
+               else
+                       snprintf(msg, sizeof msg, "connect %s!%d%s",
+                               inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
+                               r->reserved ? "!r" : "");
+               n = write(cfd, msg, strlen(msg));
+               if(n < 0){
+                       _syserrno();
+                       close(cfd);
+                       return -1;
+               }
+               close(cfd);
+               return 0;
+       case PF_UNIX:
+               /* null terminate the address */
+               if(alen == sizeof(r->raddr))
+                       alen--;
+               *(((char*)&r->raddr)+alen) = 0;
+
+               if(r->other < 0){
+                       errno = EINVAL; //EGREG;
+                       return -1;
+               }
+
+               /* put far end of our pipe in /srv */
+               snprintf(msg, sizeof msg, "UD.%d.%d", getpid(), vers++);
+               if(_sock_srv(msg, r->other) < 0){
+                       r->other = -1;
+                       return -1;
+               }
+               r->other = -1;
+
+               /* tell server the /srv file to open */
+               runix = (struct sockaddr_un*)&r->raddr;
+               _sock_srvname(file, runix->sun_path);
+               nfd = open(file, O_RDWR);
+               if(nfd < 0){
+                       _syserrno();
+                       unlink(msg);
+                       return -1;
+               }
+               if(write(nfd, msg, strlen(msg)) < 0){
+                       _syserrno();
+                       close(nfd);
+                       unlink(msg);
+                       return -1;
+               }
+               close(nfd);
+
+               /* wait for server to open it and then remove it */
+               read(fd, file, sizeof(file));
+               _sock_srvname(file, msg);
+               unlink(file);
+               return 0;
+       default:
+               errno = EAFNOSUPPORT;
+               return -1;
+       }
+}
diff --git a/user/bsd/gethostbyaddr.c b/user/bsd/gethostbyaddr.c
new file mode 100644 (file)
index 0000000..fb23993
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+int h_errno;
+
+struct hostent *gethostbyaddr (__const void *addr, __socklen_t len,
+                              int type)
+{
+       unsigned long a, y;
+       struct in_addr x;
+       __const unsigned char *p = addr;
+
+       if(type != AF_INET || len != 4){
+               h_errno = NO_RECOVERY;
+               return 0;
+       }
+
+       y = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+       x.s_addr = htonl(y);
+
+       return gethostbyname(inet_ntoa(x));
+}
diff --git a/user/bsd/gethostbyname.c b/user/bsd/gethostbyname.c
new file mode 100644 (file)
index 0000000..17ce051
--- /dev/null
@@ -0,0 +1,140 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include "priv.h"
+
+int h_errno;
+
+enum
+{
+       Nname= 6,
+};
+
+/*
+ *  for inet addresses only
+ */
+struct hostent*
+gethostbyname(const char *name)
+{
+       int i, t, fd, m;
+       char *p, *bp;
+       int nn, na;
+       unsigned long x;
+       static struct hostent h;
+       static char buf[1024];
+       static char *nptr[Nname+1];
+       static char *aptr[Nname+1];
+       static char addr[Nname][4];
+
+       h.h_name = 0;
+       t = _sock_ipattr(name);
+
+       /* connect to server */
+       fd = open("/net/cs", O_RDWR);
+       if(fd < 0){
+               _syserrno();
+               h_errno = NO_RECOVERY;
+               return 0;
+       }
+
+       /* construct the query, always expect an ip# back */
+       switch(t){
+       case Tsys:
+               snprintf(buf, sizeof buf, "!sys=%s ip=*", name);
+               break;
+       case Tdom:
+               snprintf(buf, sizeof buf, "!dom=%s ip=*", name);
+               break;
+       case Tip:
+               snprintf(buf, sizeof buf, "!ip=%s", name);
+               break;
+       }
+
+       /* query the server */
+       if(write(fd, buf, strlen(buf)) < 0){
+               _syserrno();
+               h_errno = TRY_AGAIN;
+               return 0;
+       }
+       lseek(fd, 0, 0);
+       for(i = 0; i < sizeof(buf)-1; i += m){
+               m = read(fd, buf+i, sizeof(buf) - 1 - i);
+               if(m <= 0)
+                       break;
+               buf[i+m++] = ' ';
+       }
+       close(fd);
+       buf[i] = 0;
+
+       /* parse the reply */
+       nn = na = 0;
+       for(bp = buf;;){
+               p = strchr(bp, '=');
+               if(p == 0)
+                       break;
+               *p++ = 0;
+               if(strcmp(bp, "dom") == 0){
+                       if(h.h_name == 0)
+                               h.h_name = p;
+                       if(nn < Nname)
+                               nptr[nn++] = p;
+               } else if(strcmp(bp, "sys") == 0){
+                       if(nn < Nname)
+                               nptr[nn++] = p;
+               } else if(strcmp(bp, "ip") == 0){
+                       x = inet_addr(p);
+                       x = ntohl(x);
+                       if(na < Nname){
+                               addr[na][0] = x>>24;
+                               addr[na][1] = x>>16;
+                               addr[na][2] = x>>8;
+                               addr[na][3] = x;
+                               aptr[na] = addr[na];
+                               na++;
+                       }
+               }
+               while(*p && *p != ' ')
+                       p++;
+               if(*p)
+                       *p++ = 0;
+               bp = p;
+       }
+       if(nn+na == 0){
+               h_errno = HOST_NOT_FOUND;
+               return 0;
+       }
+
+       nptr[nn] = 0;
+       aptr[na] = 0;
+       h.h_aliases = nptr;
+       h.h_addr_list = aptr;
+       h.h_length = 4;
+       h.h_addrtype = AF_INET;
+       if(h.h_name == 0)
+               h.h_name = nptr[0];
+       if(h.h_name == 0)
+               h.h_name = aptr[0];
+
+       return &h;
+}
diff --git a/user/bsd/gethostname.c b/user/bsd/gethostname.c
new file mode 100644 (file)
index 0000000..6894537
--- /dev/null
@@ -0,0 +1,33 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+
+int
+gethostname(char *name, size_t namelen)
+{
+       int n, fd;
+       char buf[128];
+
+       fd = open("/dev/sysname", O_RDONLY);
+       if(fd < 0)
+               return -1;
+       n = read(fd, buf, sizeof(buf)-1);
+       close(fd);
+       if(n <= 0)
+               return -1;
+       buf[n] = 0;
+       strncpy(name, buf, namelen);
+       name[namelen-1] = 0;
+       return 0;
+}
diff --git a/user/bsd/getpeername.c b/user/bsd/getpeername.c
new file mode 100644 (file)
index 0000000..3e628bd
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "priv.h"
+
+int getpeername (int fd, __SOCKADDR_ARG addr,
+                       socklen_t *__restrict alen)
+{
+       Rock *r;
+       int i;
+       struct sockaddr_in *rip;
+       struct sockaddr_un *runix;
+
+       r = _sock_findrock(fd, 0);
+       if(r == 0){
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       switch(r->domain){
+       case PF_INET:
+               rip = (struct sockaddr_in*)&r->raddr;
+               memmove(addr, rip, sizeof(struct sockaddr_in));
+               *alen = sizeof(struct sockaddr_in);
+               break;
+       case PF_UNIX:
+               runix = (struct sockaddr_un*)&r->raddr;
+               i = &runix->sun_path[strlen(runix->sun_path)] - (char*)runix;
+               memmove(addr, runix, i);
+               *alen = i;
+               break;
+       default:
+               errno = EAFNOSUPPORT;
+               return -1;
+       }
+       return 0;
+}
diff --git a/user/bsd/getprotobyname.c b/user/bsd/getprotobyname.c
new file mode 100644 (file)
index 0000000..1241031
--- /dev/null
@@ -0,0 +1,98 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "priv.h"
+
+extern int h_errno;
+
+enum
+{
+       Nname= 6,
+};
+
+static struct protoent r;
+
+struct protoent *getprotobyname(const char *name) {
+       int fd, i, m;
+       char *p, *bp;
+       int nn, na;
+       unsigned long x;
+       static char buf[1024], proto[1024];
+       static char *nptr[Nname+1];
+
+       /* connect to server */
+       fd = open("/net/cs", O_RDWR);
+       if(fd < 0){
+               _syserrno();
+               h_errno = NO_RECOVERY;
+               return 0;
+       }
+
+       /* construct the query, always expect a protocol# back */
+       snprintf(buf, sizeof buf, "!protocol=%s ipv4proto=*", name);
+
+       /* query the server */
+       if(write(fd, buf, strlen(buf)) < 0){
+               _syserrno();
+               h_errno = TRY_AGAIN;
+               return 0;
+       }
+       lseek(fd, 0, 0);
+       for(i = 0; i < sizeof(buf)-1; i += m){
+               m = read(fd, buf+i, sizeof(buf) - 1 - i);
+               if(m <= 0)
+                       break;
+               buf[i+m++] = ' ';
+       }
+       close(fd);
+       buf[i] = 0;
+
+       /* parse the reply */
+       nn = na = 0;
+       for(bp = buf;;){
+               p = strchr(bp, '=');
+               if(p == 0)
+                       break;
+               *p++ = 0;
+               if(strcmp(bp, "protocol") == 0){
+                       if(!nn)
+                               r.p_name = p;
+                       if(nn < Nname)
+                               nptr[nn++] = p;
+               } else if(strcmp(bp, "ipv4proto") == 0){
+                       r.p_proto = atoi(p);
+                       na++;
+               }
+               while(*p && *p != ' ')
+                       p++;
+               if(*p)
+                       *p++ = 0;
+               bp = p;
+       }
+       nptr[nn] = 0;
+       r.p_aliases = nptr;
+       if (nn+na == 0)
+               return 0;
+
+       return &r;
+}
diff --git a/user/bsd/getservbyaddr.c b/user/bsd/getservbyaddr.c
new file mode 100644 (file)
index 0000000..c383506
--- /dev/null
@@ -0,0 +1,26 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+struct servent *getservbyport (int port, __const char *proto)
+{
+       char buf[32];
+
+       snprintf(buf, sizeof buf, "%d", port);
+       return getservbyname(buf, proto);
+}
diff --git a/user/bsd/getservbyname.c b/user/bsd/getservbyname.c
new file mode 100644 (file)
index 0000000..069e57b
--- /dev/null
@@ -0,0 +1,109 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "priv.h"
+
+enum
+{
+       Nname= 6,
+};
+
+/*
+ *  for inet addresses only
+ */
+struct servent*
+getservbyname(const char *name, const char *proto)
+{
+       int i, fd, m, num;
+       char *p;
+       char *bp;
+       int nn, na;
+       static struct servent s;
+       static char buf[1024];
+       static char *nptr[Nname+1];
+
+       num = 1;
+       for(p = (char *)name; *p; p++)
+               if(!isdigit(*p))
+                       num = 0;
+
+       s.s_name = 0;
+
+       /* connect to server */
+       fd = open("/net/cs", O_RDWR);
+       if(fd < 0){
+               _syserrno();
+               return 0;
+       }
+
+       /* construct the query, always expect an ip# back */
+       if(num)
+               snprintf(buf, sizeof buf, "!port=%s %s=*", name, proto);
+       else
+               snprintf(buf, sizeof buf, "!%s=%s port=*", proto, name);
+
+       /* query the server */
+       if(write(fd, buf, strlen(buf)) < 0){
+               _syserrno();
+               return 0;
+       }
+       lseek(fd, 0, 0);
+       for(i = 0; i < sizeof(buf)-1; i += m){
+               m = read(fd, buf+i, sizeof(buf) - 1 - i);
+               if(m <= 0)
+                       break;
+               buf[i+m++] = ' ';
+       }
+       close(fd);
+       buf[i] = 0;
+
+       /* parse the reply */
+       nn = na = 0;
+       for(bp = buf;;){
+               p = strchr(bp, '=');
+               if(p == 0)
+                       break;
+               *p++ = 0;
+               if(strcmp(bp, proto) == 0){
+                       if(nn < Nname)
+                               nptr[nn++] = p;
+               } else if(strcmp(bp, "port") == 0){
+                       s.s_port = htons(atoi(p));
+               }
+               while(*p && *p != ' ')
+                       p++;
+               if(*p)
+                       *p++ = 0;
+               bp = p;
+       }
+       if(nn+na == 0)
+               return 0;
+
+       nptr[nn] = 0;
+       s.s_aliases = nptr;
+       if(s.s_name == 0)
+               s.s_name = nptr[0];
+
+       return &s;
+}
diff --git a/user/bsd/getsockname.c b/user/bsd/getsockname.c
new file mode 100644 (file)
index 0000000..b067126
--- /dev/null
@@ -0,0 +1,56 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "priv.h"
+
+int getsockname (int fd, __SOCKADDR_ARG addr,
+                socklen_t *__restrict alen)
+{
+       Rock *r;
+       int i;
+       struct sockaddr_in *lip;
+       struct sockaddr_un *lunix;
+
+       r = _sock_findrock(fd, 0);
+       if(r == 0){
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       switch(r->domain){
+       case PF_INET:
+               lip = (struct sockaddr_in*)addr;
+               _sock_ingetaddr(r, lip, alen, "local");
+               break;
+       case PF_UNIX:
+               lunix = (struct sockaddr_un*)&r->addr;
+               i = &lunix->sun_path[strlen(lunix->sun_path)] - (char*)lunix;
+               memmove(addr, lunix, i);
+               *alen = i;
+               break;
+       default:
+               errno = EAFNOSUPPORT;
+               return -1;
+       }
+       return 0;
+}
diff --git a/user/bsd/inet_addr.c b/user/bsd/inet_addr.c
new file mode 100644 (file)
index 0000000..81f9e5a
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/* where to define this? only used once? */
+unsigned long nptohl(void *p);
+
+#define CLASS(x)       (x[0]>>6)
+
+unsigned long
+inet_addr(char *from)
+{
+       int i;
+       char *p;
+       unsigned char to[4];
+       unsigned long x;
+       p = from;
+       memset(to, 0, 4);
+       for(i = 0; i < 4 && *p; i++){
+               to[i] = strtoul(p, &p, 0);
+               if(*p == '.')
+                       p++;
+       }
+
+       switch(CLASS(to)){
+       case 0: /* class A - 1 byte net */
+       case 1:
+               if(i == 3){
+                       to[3] = to[2];
+                       to[2] = to[1];
+                       to[1] = 0;
+               } else if (i == 2){
+                       to[3] = to[1];
+                       to[1] = 0;
+               }
+               break;
+       case 2: /* class B - 2 byte net */
+               if(i == 3){
+                       to[3] = to[2];
+                       to[2] = 0;
+               }
+               break;
+       }
+       x = nptohl(to);
+       x = htonl(x);
+       return x;
+}
diff --git a/user/bsd/inet_ntoa.c b/user/bsd/inet_ntoa.c
new file mode 100644 (file)
index 0000000..1ef86dd
--- /dev/null
@@ -0,0 +1,30 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+char*
+inet_ntoa(struct in_addr in)
+{
+       static char s[18];
+       unsigned char *p;       
+
+       p = (unsigned char*)&in.s_addr;
+       snprintf(s, sizeof s, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+       return s;
+}
diff --git a/user/bsd/listen.c b/user/bsd/listen.c
new file mode 100644 (file)
index 0000000..4e977a4
--- /dev/null
@@ -0,0 +1,182 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+/* socket extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "priv.h"
+
+extern int     _muxsid;
+extern void    _killmuxsid(void);
+
+/*
+ * replace the fd with a pipe and start a process to
+ * accept calls in.  this is all to make select work.
+ */
+static int
+listenproc(Rock *r, int fd)
+{
+       Rock *nr;
+       char *net;
+       int cfd, nfd, dfd;
+       int pfd[2];
+       struct stat d;
+       char *p;
+       char listen[Ctlsize];
+       char name[Ctlsize];
+
+       switch(r->stype){
+       case SOCK_DGRAM:
+               net = "udp";
+               break;
+       case SOCK_STREAM:
+               net = "tcp";
+               break;
+       }
+
+       strcpy(listen, r->ctl);
+       p = strrchr(listen, '/');
+       if(p == 0)
+               return -1;
+       strcpy(p+1, "listen");
+
+       if(pipe(pfd) < 0)
+               return -1;
+
+       /* replace fd with a pipe */
+       nfd = dup(fd);
+       dup2(pfd[0], fd);
+       close(pfd[0]);
+       fstat(fd, &d);
+       r->inode = d.st_ino;
+       r->dev = d.st_dev;
+
+       /* start listening process */
+       switch(fork()){
+       case -1:
+               close(pfd[1]);
+               close(nfd);
+               return -1;
+       case 0:
+               if(_muxsid == -1) {
+                       fork(); //_RFORK(RFNOTEG);
+                       _muxsid = getpgrp();
+               } else
+                       setpgid(getpid(), _muxsid);
+               //_RENDEZVOUS(2, _muxsid);
+               break;
+       default:
+               atexit(_killmuxsid);
+ #warning "no rendezvous for listen"
+               //_muxsid = _RENDEZVOUS(2, 0);
+               close(pfd[1]);
+               close(nfd);
+               return 0;
+       }
+
+/*     for(fd = 0; fd < 30; fd++)
+               if(fd != nfd && fd != pfd[1])
+                       close(fd);/**/
+
+       for(;;){
+               cfd = open(listen, O_RDWR);
+               if(cfd < 0)
+                       break;
+
+               dfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr);
+               if(dfd < 0)
+                       break;
+
+               if(write(pfd[1], nr->ctl, strlen(nr->ctl)) < 0)
+                       break;
+               if(read(pfd[1], name, sizeof(name)) <= 0)
+                       break;
+
+               close(dfd);
+       }
+       exit(0);
+       return 0;
+}
+
+int
+listen(fd, backlog)
+       int fd;
+       int backlog;
+{
+       Rock *r;
+       int n, cfd;
+       char msg[128];
+       struct sockaddr_in *lip;
+       struct sockaddr_un *lunix;
+
+       r = _sock_findrock(fd, 0);
+       if(r == 0){
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       switch(r->domain){
+       case PF_INET:
+               cfd = open(r->ctl, O_RDWR);
+               if(cfd < 0){
+                       errno = EBADF;
+                       return -1;
+               }
+               lip = (struct sockaddr_in*)&r->addr;
+               if(lip->sin_port >= 0) {
+                       if(write(cfd, "bind 0", 6) < 0) {
+                               errno = EINVAL; //EGREG;
+                               close(cfd);
+                               return -1;
+                       }
+                       snprintf(msg, sizeof msg, "announce %d",
+                               ntohs(lip->sin_port));
+               }
+               else
+                       strcpy(msg, "announce *");
+               n = write(cfd, msg, strlen(msg));
+               if(n < 0){
+                       errno = EOPNOTSUPP;     /* Improve error reporting!!! */
+                       close(cfd);
+                       return -1;
+               }
+               close(cfd);
+
+               return listenproc(r, fd);
+       case PF_UNIX:
+               if(r->other < 0){
+                       errno = EINVAL;//EGREG;
+                       return -1;
+               }
+               lunix = (struct sockaddr_un*)&r->addr;
+               if(_sock_srv(lunix->sun_path, r->other) < 0){
+                       _syserrno();
+                       r->other = -1;
+                       return -1;
+               }
+               r->other = -1;
+               return 0;
+       default:
+               errno = EAFNOSUPPORT;
+               return -1;
+       }
+}
diff --git a/user/bsd/nptohl.c b/user/bsd/nptohl.c
new file mode 100644 (file)
index 0000000..3a74812
--- /dev/null
@@ -0,0 +1,18 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+unsigned long
+nptohl(void *p)
+{
+       unsigned char *up;
+       unsigned long x;
+
+       up = p;
+       x = (up[0]<<24)|(up[1]<<16)|(up[2]<<8)|up[3];
+       return x;
+}
diff --git a/user/bsd/ntohl.c b/user/bsd/ntohl.c
new file mode 100644 (file)
index 0000000..502a310
--- /dev/null
@@ -0,0 +1,55 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+unsigned long
+ntohl(int x)
+{
+       unsigned long n;
+       unsigned char *p;
+
+       n = x;
+       p = (unsigned char*)&n;
+       return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
+}
+
+unsigned long
+htonl(unsigned long h)
+{
+       unsigned long n;
+       unsigned char *p;
+
+       p = (unsigned char*)&n;
+       p[0] = h>>24;
+       p[1] = h>>16;
+       p[2] = h>>8;
+       p[3] = h;
+       return n;
+}
+
+unsigned short
+ntohs(int x)
+{
+       unsigned short n;
+       unsigned char *p;
+
+       n = x;
+       p = (unsigned char*)&n;
+       return (p[0]<<8)|p[1];
+}
+
+unsigned short
+htons(unsigned short h)
+{
+       unsigned short n;
+       unsigned char *p;
+
+       p = (unsigned char*)&n;
+       p[0] = h>>8;
+       p[1] = h;
+       return n;
+}
diff --git a/user/bsd/priv.h b/user/bsd/priv.h
new file mode 100644 (file)
index 0000000..83f4353
--- /dev/null
@@ -0,0 +1,54 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+typedef struct Rock Rock;
+
+enum
+{
+       Ctlsize=        128,
+
+       /* states */
+       Sopen=  0,
+       Sbound,
+       Sconnected,
+
+       /* types of name */
+       Tsys=   0,
+       Tip,
+       Tdom,
+};
+
+/*
+ *  since BSD programs expect to perform both control and data functions
+ *  through a single fd, we need to hide enough info under a rock to
+ *  be able to open the control file when we need it.
+ */
+struct Rock
+{
+       Rock            *next;
+       unsigned long   dev;            /* inode & dev of data file */
+       unsigned long   inode;          /* ... */
+       int             domain;         /* from socket call */
+       int             stype;          /* ... */
+       int             protocol;       /* ... */
+       struct sockaddr addr;           /* address from bind */
+       int             reserved;       /* use a priveledged port # (< 1024) */
+       struct sockaddr raddr;          /* peer address */
+       char            ctl[Ctlsize];   /* name of control file (if any) */
+       int             other;          /* fd of the remote end for Unix domain */
+};
+
+extern Rock*   _sock_findrock(int, struct stat*);
+extern Rock*   _sock_newrock(int);
+extern void    _sock_srvname(char*, char*);
+extern int     _sock_srv(char*, int);
+extern int     _sock_data(int, char*, int, int, int, Rock**);
+extern int     _sock_ipattr(const char*);
+extern void    _sock_ingetaddr(Rock*, struct sockaddr_in*, int*, char*);
+
+extern void    _syserrno(void);
diff --git a/user/bsd/putenv.c b/user/bsd/putenv.c
new file mode 100644 (file)
index 0000000..cfb4a7c
--- /dev/null
@@ -0,0 +1,40 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+int
+putenv(char *s)
+{
+       int f, n;
+       char *value;
+       char buf[300];
+
+       value = strchr(s, '=');
+       if (value) {
+               n = value-s;
+               if(n<=0 || n > sizeof(buf)-6)
+                       return -1;
+               strcpy(buf, "/env/");
+               strncpy(buf+5, s, n);
+               buf[n+5] = 0;
+               f = creat(buf, 0666);
+               if(f < 0)
+                       return 1;
+               value++;
+               n = strlen(value);
+               if(write(f, value, n) != n)
+                       return -1;
+               close(f);
+               return 0;
+       } else
+               return -1;
+}
diff --git a/user/bsd/rresvport.c b/user/bsd/rresvport.c
new file mode 100644 (file)
index 0000000..c72cdca
--- /dev/null
@@ -0,0 +1,45 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+/* socket extensions */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+int
+rresvport(int *p)
+{
+       int fd;
+       short i;
+       struct  sockaddr_in in;
+       static int next;
+
+       fd = socket(PF_INET, SOCK_STREAM, 0);
+       if(fd < 0)
+               return -1;
+       i = 600 + ((getpid()+next++)%(1024-600));
+       memset(&in, 0, sizeof(in));
+       in.sin_family = AF_INET;
+       in.sin_port = htons(i);
+printf("in.sin_port = %d\n", in.sin_port);
+       if(bind(fd, (struct sockaddr *)&in, sizeof(in)) < 0){
+               close(fd);
+               return -1;
+       }
+       if(p)
+               *p = i;
+       return fd;
+}
diff --git a/user/bsd/send.c b/user/bsd/send.c
new file mode 100644 (file)
index 0000000..67afb98
--- /dev/null
@@ -0,0 +1,39 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include<arpa/inet.h>
+
+#include "priv.h"
+
+ssize_t send (int fd, __const void *a, size_t n, int flags)
+{
+       if(flags & MSG_OOB){
+               errno = EOPNOTSUPP;
+               return -1;
+       }
+       return write(fd, a, n);
+}
+
+ssize_t
+recv(int fd, void *a, size_t n, int flags)
+{
+       if(flags & MSG_OOB){
+               errno = EOPNOTSUPP;
+               return -1;
+       }
+       return read(fd, a, n);
+}
diff --git a/user/bsd/sendto.c b/user/bsd/sendto.c
new file mode 100644 (file)
index 0000000..42a1a65
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "priv.h"
+
+ssize_t sendto (int fd, __const void *a, size_t n,
+                       int flags, __CONST_SOCKADDR_ARG to,
+                       socklen_t tolen)
+{
+       /* actually, should do connect if not done already */
+       return send(fd, a, n, flags);
+}
+
+
+ssize_t recvfrom (int fd, void *__restrict a, size_t n,
+                         int flags, __SOCKADDR_ARG from,
+                         socklen_t *__restrict fromlen)
+{
+       if(getsockname(fd, from, fromlen) < 0)
+               return -1;
+       return recv(fd, a, n, flags);
+}
diff --git a/user/bsd/shutdown.c b/user/bsd/shutdown.c
new file mode 100644 (file)
index 0000000..63d63db
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+#include <sys/types.h>
+#include <unistd.h>
+
+int
+shutdown(int fd, int how)
+{
+       if(how == 2)
+               close(fd);
+
+       return 0;
+}
diff --git a/user/bsd/socket.c b/user/bsd/socket.c
new file mode 100644 (file)
index 0000000..36d025d
--- /dev/null
@@ -0,0 +1,187 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* 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 <netinet/in.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 __fd, int __level, int __optname,
+                      void *__restrict __optval,
+                      socklen_t *__restrict __optlen)
+{
+       return -1;
+}
+
+int setsockopt (int __fd, int __level, int __optname,
+                      __const void *__optval, socklen_t __optlen)
+{
+       return 0;
+}
+
diff --git a/user/bsd/socketpair.c b/user/bsd/socketpair.c
new file mode 100644 (file)
index 0000000..854d6c6
--- /dev/null
@@ -0,0 +1,29 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+int
+socketpair(int domain, int type, int protocol, int *sv)
+{
+       switch(domain){
+       case PF_UNIX:
+               return pipe(sv);
+       default:
+               errno = EOPNOTSUPP;
+               return -1;
+       }
+}