diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/bsd |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/bsd')
47 files changed, 2452 insertions, 0 deletions
diff --git a/sys/src/ape/lib/bsd/_sock_ingetaddr.c b/sys/src/ape/lib/bsd/_sock_ingetaddr.c new file mode 100755 index 000000000..bc9f90512 --- /dev/null +++ b/sys/src/ape/lib/bsd/_sock_ingetaddr.c @@ -0,0 +1,47 @@ +/* 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" + +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/sys/src/ape/lib/bsd/_sock_ipattr.c b/sys/src/ape/lib/bsd/_sock_ipattr.c new file mode 100755 index 000000000..b9b0c8ac8 --- /dev/null +++ b/sys/src/ape/lib/bsd/_sock_ipattr.c @@ -0,0 +1,45 @@ +/* posix */ +#include <sys/types.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(char *name) +{ + 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/sys/src/ape/lib/bsd/_sock_srv.c b/sys/src/ape/lib/bsd/_sock_srv.c new file mode 100755 index 000000000..1f2988d03 --- /dev/null +++ b/sys/src/ape/lib/bsd/_sock_srv.c @@ -0,0 +1,60 @@ +/* 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 "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/sys/src/ape/lib/bsd/accept.c b/sys/src/ape/lib/bsd/accept.c new file mode 100755 index 000000000..483e4c6ed --- /dev/null +++ b/sys/src/ape/lib/bsd/accept.c @@ -0,0 +1,121 @@ +/* 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" + +int +accept(int fd, void *a, int *alen) +{ + 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 = 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/sys/src/ape/lib/bsd/bcopy.c b/sys/src/ape/lib/bsd/bcopy.c new file mode 100755 index 000000000..6e3e02224 --- /dev/null +++ b/sys/src/ape/lib/bsd/bcopy.c @@ -0,0 +1,21 @@ +#include <sys/types.h> +#include <unistd.h> +#include <string.h> + +void +bcopy(void *f, void *t, size_t n) +{ + memmove(t, f, n); +} + +int +bcmp(void *a, void *b, size_t n) +{ + return memcmp(a, b, n); +} + +void +bzero(void *a, size_t n) +{ + memset(a, 0, n); +} diff --git a/sys/src/ape/lib/bsd/bind.c b/sys/src/ape/lib/bsd/bind.c new file mode 100755 index 000000000..040c62fa0 --- /dev/null +++ b/sys/src/ape/lib/bsd/bind.c @@ -0,0 +1,70 @@ +/* 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> + +/* plan 9 */ +#include "lib.h" +#include "sys9.h" + +#include "priv.h" + +int +bind(int fd, void *a, int 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/sys/src/ape/lib/bsd/connect.c b/sys/src/ape/lib/bsd/connect.c new file mode 100755 index 000000000..3f7dcd6b4 --- /dev/null +++ b/sys/src/ape/lib/bsd/connect.c @@ -0,0 +1,111 @@ +/* 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 +connect(int fd, void *a, int 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; + } + rip = 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 = 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/sys/src/ape/lib/bsd/endhostent.c b/sys/src/ape/lib/bsd/endhostent.c new file mode 100755 index 000000000..aa798b87d --- /dev/null +++ b/sys/src/ape/lib/bsd/endhostent.c @@ -0,0 +1,4 @@ +void +endhostent(void) +{ +} diff --git a/sys/src/ape/lib/bsd/ffs.c b/sys/src/ape/lib/bsd/ffs.c new file mode 100755 index 000000000..508345365 --- /dev/null +++ b/sys/src/ape/lib/bsd/ffs.c @@ -0,0 +1,23 @@ +/* Find the first set bit + * i.e. least signifigant 1 bit: + * 0 => 0 + * 1 => 1 + * 2 => 2 + * 3 => 1 + * 4 => 3 + */ + +int +ffs(unsigned int mask) +{ + int i; + + if (!mask) + return 0; + i = 1; + while (!(mask & 1)){ + i++; + mask = mask >> 1; + } + return i; +} diff --git a/sys/src/ape/lib/bsd/getdtablesize.c b/sys/src/ape/lib/bsd/getdtablesize.c new file mode 100755 index 000000000..20e23b17f --- /dev/null +++ b/sys/src/ape/lib/bsd/getdtablesize.c @@ -0,0 +1,8 @@ +/* posix */ +#include <sys/limits.h> + +int +getdtablesize(void) +{ + return OPEN_MAX; +} diff --git a/sys/src/ape/lib/bsd/gethostbyaddr.c b/sys/src/ape/lib/bsd/gethostbyaddr.c new file mode 100755 index 000000000..bd58b1dff --- /dev/null +++ b/sys/src/ape/lib/bsd/gethostbyaddr.c @@ -0,0 +1,29 @@ +/* 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> + +int h_errno; + +struct hostent* +gethostbyaddr(void *addr, int len, int type) +{ + unsigned long a, y; + struct in_addr x; + 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/sys/src/ape/lib/bsd/gethostbyname.c b/sys/src/ape/lib/bsd/gethostbyname.c new file mode 100755 index 000000000..749798510 --- /dev/null +++ b/sys/src/ape/lib/bsd/gethostbyname.c @@ -0,0 +1,131 @@ +/* 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" + +int h_errno; + +enum +{ + Nname= 6, +}; + +/* + * for inet addresses only + */ +struct hostent* +gethostbyname(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/sys/src/ape/lib/bsd/gethostname.c b/sys/src/ape/lib/bsd/gethostname.c new file mode 100755 index 000000000..5ecdd94b8 --- /dev/null +++ b/sys/src/ape/lib/bsd/gethostname.c @@ -0,0 +1,25 @@ +/* posix */ +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> + +int +gethostname(char *name, int 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/sys/src/ape/lib/bsd/getopt.c b/sys/src/ape/lib/bsd/getopt.c new file mode 100755 index 000000000..0116b1183 --- /dev/null +++ b/sys/src/ape/lib/bsd/getopt.c @@ -0,0 +1,52 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#define ERR(str, chr) if(opterr){fprintf(stderr, "%s%s%c\n", argv[0], str, chr);} +int opterr = 1; +int optind = 1; +int optopt; +char *optarg; + +int +getopt (int argc, char **argv, char *opts) +{ + static int sp = 1; + register c; + register char *cp; + + if (sp == 1) + if (optind >= argc || + argv[optind][0] != '-' || argv[optind][1] == '\0') + return EOF; + else if (strcmp(argv[optind], "--") == 0) { + optind++; + return EOF; + } + optopt = c = argv[optind][sp]; + if (c == ':' || (cp=strchr(opts, c)) == NULL) { + ERR (": illegal option -- ", c); + if (argv[optind][++sp] == '\0') { + optind++; + sp = 1; + } + return '?'; + } + if (*++cp == ':') { + if (argv[optind][sp+1] != '\0') + optarg = &argv[optind++][sp+1]; + else if (++optind >= argc) { + ERR (": option requires an argument -- ", c); + sp = 1; + return '?'; + } else + optarg = argv[optind++]; + sp = 1; + } else { + if (argv[optind][++sp] == '\0') { + sp = 1; + optind++; + } + optarg = NULL; + } + return c; +} diff --git a/sys/src/ape/lib/bsd/getpeername.c b/sys/src/ape/lib/bsd/getpeername.c new file mode 100755 index 000000000..e4dd3109c --- /dev/null +++ b/sys/src/ape/lib/bsd/getpeername.c @@ -0,0 +1,49 @@ +/* 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, struct sockaddr *addr, int *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/sys/src/ape/lib/bsd/getprotobyname.c b/sys/src/ape/lib/bsd/getprotobyname.c new file mode 100755 index 000000000..f88d70148 --- /dev/null +++ b/sys/src/ape/lib/bsd/getprotobyname.c @@ -0,0 +1,90 @@ +/* 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/sys/src/ape/lib/bsd/getservbyaddr.c b/sys/src/ape/lib/bsd/getservbyaddr.c new file mode 100755 index 000000000..cafb72d04 --- /dev/null +++ b/sys/src/ape/lib/bsd/getservbyaddr.c @@ -0,0 +1,18 @@ +#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> + +struct servent* +getservbyport(int port, char *proto) +{ + char buf[32]; + + snprintf(buf, sizeof buf, "%d", port); + return getservbyname(buf, proto); +} diff --git a/sys/src/ape/lib/bsd/getservbyname.c b/sys/src/ape/lib/bsd/getservbyname.c new file mode 100755 index 000000000..0212d5403 --- /dev/null +++ b/sys/src/ape/lib/bsd/getservbyname.c @@ -0,0 +1,100 @@ +/* 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(char *name, char *proto) +{ + int i, fd, m, num; + char *p, *bp; + int nn, na; + static struct servent s; + static char buf[1024]; + static char *nptr[Nname+1]; + + num = 1; + for(p = 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/sys/src/ape/lib/bsd/getsockname.c b/sys/src/ape/lib/bsd/getsockname.c new file mode 100755 index 000000000..aa22d3217 --- /dev/null +++ b/sys/src/ape/lib/bsd/getsockname.c @@ -0,0 +1,48 @@ +/* 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, struct sockaddr *addr, int *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/sys/src/ape/lib/bsd/gettimeofday.c b/sys/src/ape/lib/bsd/gettimeofday.c new file mode 100755 index 000000000..ee347f36a --- /dev/null +++ b/sys/src/ape/lib/bsd/gettimeofday.c @@ -0,0 +1,56 @@ +#include <sys/types.h> +#include <time.h> +#include <sys/time.h> +#include <string.h> +#include "sys9.h" + +typedef unsigned long long uvlong; +typedef long long vlong; +typedef unsigned char uchar; + +static uvlong order = 0x0001020304050607ULL; + +static void +be2vlong(vlong *to, uchar *f) +{ + uchar *t, *o; + int i; + + t = (uchar*)to; + o = (uchar*)ℴ + for(i = 0; i < 8; i++) + t[o[i]] = f[i]; +} + +int +gettimeofday(struct timeval *tp, struct timezone *tzp) +{ + uchar b[8]; + vlong t; + int opened; + static int fd = -1; + + opened = 0; + for(;;) { + if(fd < 0) + if(opened++ || + (fd = _OPEN("/dev/bintime", OREAD|OCEXEC)) < 0) + return 0; + if(_PREAD(fd, b, sizeof b, 0) == sizeof b) + break; /* leave fd open for future use */ + /* short read, perhaps try again */ + _CLOSE(fd); + fd = -1; + } + be2vlong(&t, b); + + tp->tv_sec = t/1000000000; + tp->tv_usec = (t/1000)%1000000; + + if(tzp) { + tzp->tz_minuteswest = 4*60; /* BUG */ + tzp->tz_dsttime = 1; + } + + return 0; +} diff --git a/sys/src/ape/lib/bsd/inet_addr.c b/sys/src/ape/lib/bsd/inet_addr.c new file mode 100755 index 000000000..63cd69cc4 --- /dev/null +++ b/sys/src/ape/lib/bsd/inet_addr.c @@ -0,0 +1,52 @@ +/* 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> + +#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/sys/src/ape/lib/bsd/inet_ntoa.c b/sys/src/ape/lib/bsd/inet_ntoa.c new file mode 100755 index 000000000..03dd714dd --- /dev/null +++ b/sys/src/ape/lib/bsd/inet_ntoa.c @@ -0,0 +1,22 @@ +/* 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/sys/src/ape/lib/bsd/ioctl.c b/sys/src/ape/lib/bsd/ioctl.c new file mode 100755 index 000000000..0155de573 --- /dev/null +++ b/sys/src/ape/lib/bsd/ioctl.c @@ -0,0 +1,33 @@ +/* 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 <sys/ioctl.h> + +int +ioctl(int fd, unsigned long request, void* arg) +{ + struct stat d; + + if(request == FIONREAD) { + if(fstat(fd, &d) < 0) { + errno = EBADF; + return -1; + } + /* this works if the file is buffered somehow */ + *(long*)arg = d.st_size; + return 0; + } else { + errno = EINVAL; + return -1; + } +} diff --git a/sys/src/ape/lib/bsd/listen.c b/sys/src/ape/lib/bsd/listen.c new file mode 100755 index 000000000..655e2a06f --- /dev/null +++ b/sys/src/ape/lib/bsd/listen.c @@ -0,0 +1,176 @@ +/* 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> + +/* plan 9 */ +#include "lib.h" +#include "sys9.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) { + _RFORK(RFNOTEG); + _muxsid = getpgrp(); + } else + setpgid(getpid(), _muxsid); + _RENDEZVOUS(2, _muxsid); + break; + default: + atexit(_killmuxsid); + _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); +} + +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 = 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 = 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/sys/src/ape/lib/bsd/lstat.c b/sys/src/ape/lib/bsd/lstat.c new file mode 100755 index 000000000..d929e7ef1 --- /dev/null +++ b/sys/src/ape/lib/bsd/lstat.c @@ -0,0 +1,23 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + +int +lstat(char *name, struct stat *ans) +{ + return stat(name, ans); +} + +int +symlink(char *name1, char *name2) +{ + errno = EPERM; + return -1; +} + +int +readlink(char *name, char *buf, int size) +{ + errno = EIO; + return -1; +} diff --git a/sys/src/ape/lib/bsd/mkfile b/sys/src/ape/lib/bsd/mkfile new file mode 100755 index 000000000..44b4b05fb --- /dev/null +++ b/sys/src/ape/lib/bsd/mkfile @@ -0,0 +1,55 @@ +APE=/sys/src/ape +<$APE/config + +LIB=/$objtype/lib/ape/libbsd.a +OFILES=\ + accept.$O\ + bcopy.$O\ + bind.$O\ + connect.$O\ + endhostent.$O\ + ffs.$O\ + getdtablesize.$O\ + gethostbyname.$O\ + gethostbyaddr.$O\ + gethostname.$O\ + getopt.$O\ + getpeername.$O\ + getprotobyname.$O\ + getservbyaddr.$O\ + getservbyname.$O\ + getsockname.$O\ + gettimeofday.$O\ + inet_addr.$O\ + inet_ntoa.$O\ + ioctl.$O\ + listen.$O\ + lstat.$O\ + mktemp.$O\ + ntohl.$O\ + nptohl.$O\ + popen.$O\ + putenv.$O\ + rcmd.$O\ + readv.$O\ + rresvport.$O\ + send.$O\ + sendto.$O\ + setlinebuf.$O\ + shutdown.$O\ + _sock_ingetaddr.$O\ + _sock_ipattr.$O\ + _sock_srv.$O\ + strcasecmp.$O\ + strncasecmp.$O\ + socket.$O\ + socketpair.$O\ + strdup.$O\ + pty.$O\ + writev.$O\ + +HFILES=priv.h + +</sys/src/cmd/mksyslib + +CFLAGS=-c -D_POSIX_SOURCE -D_BSD_EXTENSION -D_PLAN9_SOURCE -I../ap/plan9 diff --git a/sys/src/ape/lib/bsd/mktemp.c b/sys/src/ape/lib/bsd/mktemp.c new file mode 100755 index 000000000..d48714a32 --- /dev/null +++ b/sys/src/ape/lib/bsd/mktemp.c @@ -0,0 +1,33 @@ +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +char* +mktemp(char *template) +{ + int n; + long x; + char *p; + int c; + struct stat stbuf; + + n = strlen(template); + p = template+n-6; + if (n < 6 || strcmp(p, "XXXXXX") != 0) { + *template = 0; + } else { + x = getpid() % 100000; + sprintf(p, "%05d", x); + p += 5; + for(c = 'a'; c <= 'z'; c++) { + *p = c; + if (stat(template, &stbuf) < 0) + return template; + } + *template = 0; + } + return template; +} diff --git a/sys/src/ape/lib/bsd/nptohl.c b/sys/src/ape/lib/bsd/nptohl.c new file mode 100755 index 000000000..c012493e9 --- /dev/null +++ b/sys/src/ape/lib/bsd/nptohl.c @@ -0,0 +1,10 @@ +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/sys/src/ape/lib/bsd/ntohl.c b/sys/src/ape/lib/bsd/ntohl.c new file mode 100755 index 000000000..29c19d6fb --- /dev/null +++ b/sys/src/ape/lib/bsd/ntohl.c @@ -0,0 +1,47 @@ +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/sys/src/ape/lib/bsd/popen.c b/sys/src/ape/lib/bsd/popen.c new file mode 100755 index 000000000..32af1de3d --- /dev/null +++ b/sys/src/ape/lib/bsd/popen.c @@ -0,0 +1,84 @@ +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/wait.h> + +#define MAXFORKS 20 +#define NSYSFILE 3 +#define tst(a,b) (*mode == 'r'? (b) : (a)) +#define RDR 0 +#define WTR 1 + +struct a_fork { + short done; + short fd; + int pid; + int status; +}; +static struct a_fork the_fork[MAXFORKS]; + +FILE * +popen(char *cmd, char *mode) +{ + int p[2]; + int myside, hisside, pid; + int i, ind; + + for (ind = 0; ind < MAXFORKS; ind++) + if (the_fork[ind].pid == 0) + break; + if (ind == MAXFORKS) + return NULL; + if(pipe(p) < 0) + return NULL; + myside = tst(p[WTR], p[RDR]); + hisside = tst(p[RDR], p[WTR]); + switch (pid = fork()) { + case -1: + return NULL; + case 0: + /* myside and hisside reverse roles in child */ + close(myside); + dup2(hisside, tst(0, 1)); + for (i=NSYSFILE; i<FOPEN_MAX; i++) + close(i); + execl("/bin/ape/sh", "sh", "-c", cmd, NULL); + _exit(1); + default: + the_fork[ind].pid = pid; + the_fork[ind].fd = myside; + the_fork[ind].done = 0; + close(hisside); + return(fdopen(myside, mode)); + } +} + +int +pclose(FILE *ptr) +{ + int f, r, ind; + int status; + + f = fileno(ptr); + fclose(ptr); + for (ind = 0; ind < MAXFORKS; ind++) + if (the_fork[ind].fd == f && the_fork[ind].pid != 0) + break; + if (ind == MAXFORKS) + return 0; + if (!the_fork[ind].done) { + do { + r = wait(&status); + for (f = 0; f < MAXFORKS; f++) + if (the_fork[f].pid == r) { + the_fork[f].done = 1; + the_fork[f].status = status; + break; + } + } while(r != the_fork[ind].pid && r != -1); + the_fork[ind].status = r == -1 ? -1 : status; + } + the_fork[ind].pid = 0; + return (the_fork[ind].status); +} diff --git a/sys/src/ape/lib/bsd/priv.h b/sys/src/ape/lib/bsd/priv.h new file mode 100755 index 000000000..f99fc5673 --- /dev/null +++ b/sys/src/ape/lib/bsd/priv.h @@ -0,0 +1,46 @@ +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(char*); +extern void _sock_ingetaddr(Rock*, struct sockaddr_in*, int*, char*); + +extern void _syserrno(void); diff --git a/sys/src/ape/lib/bsd/pty.c b/sys/src/ape/lib/bsd/pty.c new file mode 100755 index 000000000..3189d24e1 --- /dev/null +++ b/sys/src/ape/lib/bsd/pty.c @@ -0,0 +1,111 @@ +/* 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> + +#include <sys/pty.h> +#include "lib.h" +#include "sys9.h" +#include "dir.h" + +/* + * return the name of the slave + */ +char* +ptsname(int fd) +{ + Dir *d; + static char buf[32]; + + if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){ + free(d); + _syserrno(); + return 0; + } + snprintf(buf, sizeof buf, "/dev/ptty%d", atoi(d->name+4)); + free(d); + return buf; +} + +/* + * return the name of the master + */ +char* +ptmname(int fd) +{ + Dir *d; + static char buf[32]; + + if((d = _dirfstat(fd)) == nil || strlen(d->name) < 4){ + free(d); + _syserrno(); + return 0; + } + + snprintf(buf, sizeof buf, "/dev/ttym%d", atoi(d->name+4)); + return buf; +} + +static char ptycl[] = "/dev/ptyclone"; +static char fssrv[] = "/srv/ptyfs"; + +static void +mkserver(void) +{ + int fd, i; + char *argv[3]; + + fd = _OPEN(fssrv, O_RDWR); + if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0) { + /* + * remove fssrv here, if it exists, to avoid a race + * between the loop in the default case below and the + * new ptyfs removing fssrv when it starts. + * we otherwise might be unlucky enough to open the old + * (hung channel) fssrv before ptyfs removes it and break + * out of the loop with an open fd to a hung channel? + */ + _CLOSE(fd); + _REMOVE(fssrv); + switch(_RFORK(RFPROC|RFFDG)) { + case -1: + return; + case 0: + argv[0] = "ptyfs"; + argv[1] = 0; + _EXEC("/bin/ape/ptyfs", argv); + _EXITS(0); + default: + for(i = 0; i < 3; i++) { + fd = _OPEN(fssrv, O_RDWR); + if(fd >= 0) + break; + _SLEEP(1000); + } + } + if(fd < 0) + return; + if(_MOUNT(fd, -1, "/dev", MAFTER, "") < 0) + _CLOSE(fd); + } + /* successful _MOUNT closes fd */ +} + +/* + * allocate a new pty + */ +int +_getpty(void) +{ + struct stat sb; + + if(stat(ptycl, &sb) < 0) + mkserver(); + + return open(ptycl, O_RDWR); +} diff --git a/sys/src/ape/lib/bsd/putenv.c b/sys/src/ape/lib/bsd/putenv.c new file mode 100755 index 000000000..63695ba76 --- /dev/null +++ b/sys/src/ape/lib/bsd/putenv.c @@ -0,0 +1,32 @@ +#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/sys/src/ape/lib/bsd/rcmd.c b/sys/src/ape/lib/bsd/rcmd.c new file mode 100755 index 000000000..bac11735f --- /dev/null +++ b/sys/src/ape/lib/bsd/rcmd.c @@ -0,0 +1,138 @@ +/* posix */ +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <signal.h> + +/* socket extensions */ +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/un.h> +#include <netdb.h> + +#include "priv.h" + +static char pbotch[] = "rcmd: protocol botch\n"; +static char lbotch[] = "rcmd: botch starting error stream\n"; + +static void +ding(int x) +{ +} + +int +rcmd(char **dst, int port, char *luser, char *ruser, char *cmd, int *fd2p) +{ + char c; + int i, fd, lfd, fd2, port2; + struct hostent *h; + Rock *r; + struct sockaddr_in in; + char buf[128]; + void (*x)(int); + + h = gethostbyname(*dst); + if(h == 0) + return -1; + *dst = h->h_name; + + /* connect using a reserved tcp port */ + fd = socket(PF_INET, SOCK_STREAM, 0); + if(fd < 0) + return -1; + r = _sock_findrock(fd, 0); + if(r == 0){ + errno = ENOTSOCK; + return -1; + } + r->reserved = 1; + in.sin_family = AF_INET; + in.sin_port = htons(port); + memmove(&in.sin_addr, h->h_addr_list[0], sizeof(in.sin_addr)); + if(connect(fd, &in, sizeof(in)) < 0){ + close(fd); + return -1; + } + + /* error stream */ + if(fd2p){ + /* create an error stream and wait for a call in */ + for(i = 0; i < 10; i++){ + lfd = rresvport(&port2); + if(lfd < 0) + continue; + if(listen(lfd, 1) == 0) + break; + close(lfd); + } + if(i >= 10){ + fprintf(stderr, pbotch); + return -1; + } + + snprintf(buf, sizeof buf, "%d", port2); + if(write(fd, buf, strlen(buf)+1) < 0){ + close(fd); + close(lfd); + fprintf(stderr, lbotch); + return -1; + } + } else { + if(write(fd, "", 1) < 0){ + fprintf(stderr, pbotch); + return -1; + } + } + + /* pass id's and command */ + if(write(fd, luser, strlen(luser)+1) < 0 + || write(fd, ruser, strlen(ruser)+1) < 0 + || write(fd, cmd, strlen(cmd)+1) < 0){ + if(fd2p) + close(fd2); + fprintf(stderr, pbotch); + return -1; + } + + if(fd2p){ + x = signal(SIGALRM, ding); + alarm(15); + fd2 = accept(lfd, &in, &i); + alarm(0); + close(lfd); + signal(SIGALRM, x); + + if(fd2 < 0){ + close(fd); + close(lfd); + fprintf(stderr, lbotch); + return -1; + } + *fd2p = fd2; + } + + /* get reply */ + if(read(fd, &c, 1) != 1){ + if(fd2p) + close(fd2); + fprintf(stderr, pbotch); + return -1; + } + if(c == 0) + return fd; + i = 0; + while(c){ + buf[i++] = c; + if(read(fd, &c, 1) != 1) + break; + if(i >= sizeof(buf)-1) + break; + } + buf[i] = 0; + fprintf(stderr, "rcmd: %s\n", buf); + close(fd); + return -1; +} diff --git a/sys/src/ape/lib/bsd/readv.c b/sys/src/ape/lib/bsd/readv.c new file mode 100755 index 000000000..91a7157d0 --- /dev/null +++ b/sys/src/ape/lib/bsd/readv.c @@ -0,0 +1,30 @@ +#include <unistd.h> +#include <string.h> +#include <sys/uio.h> + +int +readv(int fd, struct iovec *v, int ent) +{ + int x, i, n, len; + char *t; + char buf[10*1024]; + + for(len = i = 0; i < ent; i++) + len += v[i].iov_len; + if(len > sizeof(buf)) + len = sizeof(buf); + + len = read(fd, buf, len); + if(len <= 0) + return len; + + for(n = i = 0; n < len && i < ent; i++){ + x = len - n; + if(x > v[i].iov_len) + x = v[i].iov_len; + memmove(v[i].iov_base, buf + n, x); + n += x; + } + + return len; +} diff --git a/sys/src/ape/lib/bsd/rresvport.c b/sys/src/ape/lib/bsd/rresvport.c new file mode 100755 index 000000000..6df09c87d --- /dev/null +++ b/sys/src/ape/lib/bsd/rresvport.c @@ -0,0 +1,37 @@ +/* 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, &in, sizeof(in)) < 0){ + close(fd); + return -1; + } + if(p) + *p = i; + return fd; +} diff --git a/sys/src/ape/lib/bsd/send.c b/sys/src/ape/lib/bsd/send.c new file mode 100755 index 000000000..e46346a03 --- /dev/null +++ b/sys/src/ape/lib/bsd/send.c @@ -0,0 +1,31 @@ +/* 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 "priv.h" + +int +send(int fd, char *a, int n, int flags) +{ + if(flags & MSG_OOB){ + errno = EOPNOTSUPP; + return -1; + } + return write(fd, a, n); +} + +int +recv(int fd, char *a, int n, int flags) +{ + if(flags & MSG_OOB){ + errno = EOPNOTSUPP; + return -1; + } + return read(fd, a, n); +} diff --git a/sys/src/ape/lib/bsd/sendto.c b/sys/src/ape/lib/bsd/sendto.c new file mode 100755 index 000000000..0ab450471 --- /dev/null +++ b/sys/src/ape/lib/bsd/sendto.c @@ -0,0 +1,28 @@ +/* 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 "priv.h" + +int +sendto(int fd, void *a, int n, int flags, + void *to, int tolen) +{ + /* actually, should do connect if not done already */ + return send(fd, a, n, flags); +} + +int +recvfrom(int fd, void *a, int n, int flags, + void *from, int *fromlen) +{ + if(getsockname(fd, from, fromlen) < 0) + return -1; + return recv(fd, a, n, flags); +} diff --git a/sys/src/ape/lib/bsd/sethostent.c b/sys/src/ape/lib/bsd/sethostent.c new file mode 100755 index 000000000..73867c96b --- /dev/null +++ b/sys/src/ape/lib/bsd/sethostent.c @@ -0,0 +1,5 @@ +int +sethostent(int) +{ + return 0; +} diff --git a/sys/src/ape/lib/bsd/setlinebuf.c b/sys/src/ape/lib/bsd/setlinebuf.c new file mode 100755 index 000000000..acc907e8d --- /dev/null +++ b/sys/src/ape/lib/bsd/setlinebuf.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +void +setlinebuf(FILE *f) +{ + static char buf[BUFSIZ]; + + setvbuf (f, buf, _IOLBF, BUFSIZ); +} diff --git a/sys/src/ape/lib/bsd/shutdown.c b/sys/src/ape/lib/bsd/shutdown.c new file mode 100755 index 000000000..dcb15a847 --- /dev/null +++ b/sys/src/ape/lib/bsd/shutdown.c @@ -0,0 +1,11 @@ +#include <sys/types.h> +#include <unistd.h> + +int +shutdown(int fd, int how) +{ + if(how == 2) + close(fd); + + return 0; +} 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; +} + diff --git a/sys/src/ape/lib/bsd/socketpair.c b/sys/src/ape/lib/bsd/socketpair.c new file mode 100755 index 000000000..990c3f77f --- /dev/null +++ b/sys/src/ape/lib/bsd/socketpair.c @@ -0,0 +1,21 @@ +/* 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; + } +} diff --git a/sys/src/ape/lib/bsd/strcasecmp.c b/sys/src/ape/lib/bsd/strcasecmp.c new file mode 100755 index 000000000..7fb8c8a80 --- /dev/null +++ b/sys/src/ape/lib/bsd/strcasecmp.c @@ -0,0 +1,28 @@ +#include <string.h> + +typedef unsigned char uchar; + + +int +strcasecmp(char *s1, char *s2) +{ + int c1, c2; + + while(*s1){ + c1 = *(uchar*)s1++; + c2 = *(uchar*)s2++; + + if(c1 == c2) + continue; + + if(c1 >= 'A' && c1 <= 'Z') + c1 -= 'A' - 'a'; + + if(c2 >= 'A' && c2 <= 'Z') + c2 -= 'A' - 'a'; + + if(c1 != c2) + return c1 - c2; + } + return -*s2; +} diff --git a/sys/src/ape/lib/bsd/strdup.c b/sys/src/ape/lib/bsd/strdup.c new file mode 100755 index 000000000..5e4a3759e --- /dev/null +++ b/sys/src/ape/lib/bsd/strdup.c @@ -0,0 +1,16 @@ +#include <string.h> +#include <ctype.h> +#include <stdlib.h> + +char* +strdup(char *p) +{ + int n; + char *np; + + n = strlen(p)+1; + np = malloc(n); + if(np) + memmove(np, p, n); + return np; +} diff --git a/sys/src/ape/lib/bsd/strncasecmp.c b/sys/src/ape/lib/bsd/strncasecmp.c new file mode 100755 index 000000000..a9ddc8dee --- /dev/null +++ b/sys/src/ape/lib/bsd/strncasecmp.c @@ -0,0 +1,29 @@ +#include <string.h> + +typedef unsigned char uchar; + +int +strncasecmp(char *s1, char *s2, int n) +{ + int c1, c2; + + while(*s1 && n-- > 0){ + c1 = *(uchar*)s1++; + c2 = *(uchar*)s2++; + + if(c1 == c2) + continue; + + if(c1 >= 'A' && c1 <= 'Z') + c1 -= 'A' - 'a'; + + if(c2 >= 'A' && c2 <= 'Z') + c2 -= 'A' - 'a'; + + if(c1 != c2) + return c1 - c2; + } + if(n <= 0) + return 0; + return -*s2; +} diff --git a/sys/src/ape/lib/bsd/writev.c b/sys/src/ape/lib/bsd/writev.c new file mode 100755 index 000000000..fbb36b692 --- /dev/null +++ b/sys/src/ape/lib/bsd/writev.c @@ -0,0 +1,62 @@ +#include <sys/types.h> +#include <unistd.h> +#include <string.h> + +/* bsd extensions */ +#include <sys/uio.h> +#include <sys/socket.h> + +#include "priv.h" + +int +writev(int fd, struct iovec *v, int ent) +{ + int i, n, written; + char *t, *e, *f; + char buf[10*1024]; + + written = n = 0; + t = buf; + e = buf+sizeof(buf); + for(;ent ; v++, ent--){ + n = v->iov_len; + f = v->iov_base; + while(n > 0){ + i = e-t; + if(n < i){ + memmove(t, f, n); + t += n; + break; + } + memmove(t, f, i); + n -= i; + f += i; + i = write(fd, buf, sizeof(buf)); + if(i < 0){ + if(written > 0){ + return written; + }else{ + _syserrno(); + return -1; + } + } + written += i; + if(i != sizeof(buf)) { + return written; + } + t = buf; + } + } + i = t - buf; + if(i > 0){ + n = write(fd, buf, i); + if(n < 0){ + if(written == 0){ + _syserrno(); + return -1; + } + } else + written += n; + } + return written; +} |