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/connect.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/bsd/connect.c')
-rwxr-xr-x | sys/src/ape/lib/bsd/connect.c | 111 |
1 files changed, 111 insertions, 0 deletions
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; + } +} |