minix/lib/libc/sys-minix/socketpair.c
Lionel Sambuc 84d9c625bf Synchronize on NetBSD-CVS (2013/12/1 12:00:00 UTC)
- Fix for possible unset uid/gid in toproto
 - Fix for default mtree style
 - Update libelf
 - Importing libexecinfo
 - Resynchronize GCC, mpc, gmp, mpfr
 - build.sh: Replace params with show-params.
     This has been done as the make target has been renamed in the same
     way, while a new target named params has been added. This new
     target generates a file containing all the parameters, instead of
     printing it on the console.
 - Update test48 with new etc/services (Fix by Ben Gras <ben@minix3.org)
     get getservbyport() out of the inner loop

Change-Id: Ie6ad5226fa2621ff9f0dee8782ea48f9443d2091
2014-07-28 17:05:06 +02:00

140 lines
2.5 KiB
C

#include <sys/cdefs.h>
#include "namespace.h"
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <net/netlib.h>
#include <sys/ioc_net.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#define DEBUG 0
static int _uds_socketpair(int type, int protocol, int sv[2]);
/*
* Create a pair of connected sockets
*/
int socketpair(int domain, int type, int protocol, int sv[2]) {
#if DEBUG
fprintf(stderr, "socketpair: domain %d, type %d, protocol %d\n",
domain, type, protocol);
#endif
if (domain != AF_UNIX)
{
errno = EAFNOSUPPORT;
return -1;
}
if (domain == AF_UNIX &&
(type == SOCK_STREAM || type == SOCK_SEQPACKET))
return _uds_socketpair(type, protocol, sv);
#if DEBUG
fprintf(stderr,
"socketpair: nothing for domain %d, type %d, protocol %d\n",
domain, type, protocol);
#endif
errno= EPROTOTYPE;
return -1;
}
static int _uds_socketpair(int type, int protocol, int sv[2])
{
dev_t dev;
int r, i;
struct stat sbuf;
if (protocol != 0)
{
#if DEBUG
fprintf(stderr, "socketpair(uds): bad protocol %d\n", protocol);
#endif
errno= EPROTONOSUPPORT;
return -1;
}
/* in this 'for' loop two unconnected sockets are created */
for (i = 0; i < 2; i++) {
sv[i]= open(UDS_DEVICE, O_RDWR);
if (sv[i] == -1) {
int open_errno = errno;
if (i == 1) {
/* if we failed to open() the 2nd
* socket, we need to close the 1st
*/
close(sv[0]);
errno = open_errno;
}
return -1;
}
/* set the type for the socket via ioctl
* (SOCK_STREAM, SOCK_SEQPACKET, etc)
*/
r= ioctl(sv[i], NWIOSUDSTYPE, &type);
if (r == -1) {
int ioctl_errno;
/* if that failed rollback socket creation */
ioctl_errno= errno;
close(sv[i]);
if (i == 1) {
/* if we just closed the 2nd socket, we
* need to close the 1st
*/
close(sv[0]);
}
/* return the error thrown by the call to ioctl */
errno= ioctl_errno;
return -1;
}
}
r= fstat(sv[1], &sbuf);
if (r == -1) {
int fstat_errno;
/* if that failed rollback socket creation */
fstat_errno= errno;
close(sv[0]);
close(sv[1]);
/* return the error thrown by the call to fstat */
errno= fstat_errno;
return -1;
}
dev = sbuf.st_dev;
/* connect the sockets sv[0] and sv[1] */
r= ioctl(sv[0], NWIOSUDSPAIR, &dev);
if (r == -1) {
int ioctl_errno;
/* if that failed rollback socket creation */
ioctl_errno= errno;
close(sv[0]);
close(sv[1]);
/* return the error thrown by the call to ioctl */
errno= ioctl_errno;
return -1;
}
return 0;
}