etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libc / sys / socketpair.c
blob1b1767dcd773a12bd1d8987b363fc832598c0e55
1 #include <sys/cdefs.h>
2 #include "namespace.h"
3 #include <lib.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <stdio.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <net/netlib.h>
11 #include <sys/ioctl.h>
12 #include <sys/ioc_net.h>
13 #include <sys/socket.h>
14 #include <sys/stat.h>
15 #include <sys/un.h>
17 #define DEBUG 0
19 static int _uds_socketpair(int type, int protocol, int sv[2]);
22 * Create a pair of connected sockets.
24 static int
25 __socketpair(int domain, int type, int protocol, int sv[2])
27 message m;
29 memset(&m, 0, sizeof(m));
30 m.m_lc_vfs_socket.domain = domain;
31 m.m_lc_vfs_socket.type = type;
32 m.m_lc_vfs_socket.protocol = protocol;
34 if (_syscall(VFS_PROC_NR, VFS_SOCKETPAIR, &m) < 0)
35 return -1;
37 sv[0] = m.m_vfs_lc_fdpair.fd0;
38 sv[1] = m.m_vfs_lc_fdpair.fd1;
39 return 0;
42 int
43 socketpair(int domain, int type, int protocol, int sv[2])
45 int r;
47 r = __socketpair(domain, type, protocol, sv);
48 if (r != -1 || (errno != EAFNOSUPPORT && errno != ENOSYS))
49 return r;
51 #if DEBUG
52 fprintf(stderr, "socketpair: domain %d, type %d, protocol %d\n",
53 domain, type, protocol);
54 #endif
56 if (domain == AF_UNIX)
57 return _uds_socketpair(type, protocol, sv);
59 errno = EAFNOSUPPORT;
60 return -1;
63 static int _uds_socketpair(int type, int protocol, int sv[2])
65 dev_t dev;
66 int r, i;
67 struct stat sbuf;
69 if (type != SOCK_STREAM && type != SOCK_SEQPACKET) {
70 errno = EPROTOTYPE;
71 return -1;
74 if (protocol != 0)
76 #if DEBUG
77 fprintf(stderr, "socketpair(uds): bad protocol %d\n", protocol);
78 #endif
79 errno= EPROTONOSUPPORT;
80 return -1;
83 /* in this 'for' loop two unconnected sockets are created */
84 for (i = 0; i < 2; i++) {
85 sv[i]= open(UDS_DEVICE, O_RDWR);
86 if (sv[i] == -1) {
87 int open_errno = errno;
89 if (i == 1) {
90 /* if we failed to open() the 2nd
91 * socket, we need to close the 1st
93 close(sv[0]);
94 errno = open_errno;
97 return -1;
100 /* set the type for the socket via ioctl
101 * (SOCK_STREAM, SOCK_SEQPACKET, etc)
103 r= ioctl(sv[i], NWIOSUDSTYPE, &type);
104 if (r == -1) {
105 int ioctl_errno;
107 /* if that failed rollback socket creation */
108 ioctl_errno= errno;
109 close(sv[i]);
111 if (i == 1) {
112 /* if we just closed the 2nd socket, we
113 * need to close the 1st
115 close(sv[0]);
118 /* return the error thrown by the call to ioctl */
119 errno= ioctl_errno;
120 return -1;
124 r= fstat(sv[1], &sbuf);
125 if (r == -1) {
126 int fstat_errno;
128 /* if that failed rollback socket creation */
129 fstat_errno= errno;
131 close(sv[0]);
132 close(sv[1]);
134 /* return the error thrown by the call to fstat */
135 errno= fstat_errno;
136 return -1;
139 dev = sbuf.st_rdev;
141 /* connect the sockets sv[0] and sv[1] */
142 r= ioctl(sv[0], NWIOSUDSPAIR, &dev);
143 if (r == -1) {
144 int ioctl_errno;
146 /* if that failed rollback socket creation */
147 ioctl_errno= errno;
149 close(sv[0]);
150 close(sv[1]);
152 /* return the error thrown by the call to ioctl */
153 errno= ioctl_errno;
154 return -1;
158 return 0;