blob: 0bb32dab0f9f5651c9cd01b0a9a07cb4808ab0a5 [file] [log] [blame]
/* On AIX 5.2, _LINUX_SOURCE_COMPAT needs to be defined when reading
sys/socket.h in order to make CMSG_SPACE and CMSG_LEN visible. */
#if defined(_AIX)
#define _LINUX_SOURCE_COMPAT 1
#endif
#include <sys/socket.h>
#if defined(_AIX)
#undef _LINUX_SOURCE_COMPAT
#endif
/* Needed for 'memset' on AIX 5.2 */
#if defined(_AIX)
# include <memory.h>
#endif
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include "fdleak.h"
char filea[24];
char fileb[24];
char sock[24];
void server (void)
{
int s, fd1, fd2;
struct sockaddr_un addr;
fd1 = DO( open(filea, O_RDWR | O_CREAT | O_TRUNC, 0750) );
fd2 = DO( open(fileb, O_RDWR | O_CREAT | O_TRUNC, 0750) );
s = DO( socket(PF_UNIX, SOCK_STREAM, 0) );
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
sprintf(addr.sun_path, "%s", sock);
unlink(sock);
DO( bind(s, (struct sockaddr *)&addr, sizeof(addr)) );
DO( listen(s, 5) );
{
int x;
int baddrsize = 0;
struct sockaddr_un baddr;
struct msghdr msg = {NULL, 0, NULL, 0, 0, 0, 0};
struct cmsghdr *cmsg;
char buf[CMSG_SPACE(sizeof(int) * 2)];
struct iovec iov[1];
memset(&baddr, 0, sizeof(baddr));
x = DO( accept(s, (struct sockaddr *)&baddr, &baddrsize) );
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * 2);
((int *)CMSG_DATA(cmsg))[0] = fd1;
((int *)CMSG_DATA(cmsg))[1] = fd2;
iov[0].iov_base = "hello";
iov[0].iov_len = 6;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
DO( sendmsg(x, &msg, 0) );
}
}
void client (void)
{
int s, fd1 = -1, fd2 = -1, size, count = 0, ret;
struct sockaddr_un addr;
struct iovec iov[1];
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int) * 2)];
} control_un;
struct msghdr msg = { NULL, 0, iov, 1, control_un.control,
sizeof(control_un), 0 };
struct cmsghdr *cmsg = &control_un.cm;
char buf[1024];
iov[0].iov_base = buf;
iov[0].iov_len = sizeof(buf);
s = socket(PF_UNIX, SOCK_STREAM, 0);
if (s == -1) {
perror("socket");
exit(1);
}
addr.sun_family = AF_UNIX;
sprintf(addr.sun_path, "%s", sock);
do {
count++;
ret = connect(s, (struct sockaddr *)&addr, sizeof(addr));
if (ret == -1) sleep(1);
} while (count < 10 && ret == -1);
if (ret == -1) {
perror("connect");
exit(1);
}
again:
if ((size = recvmsg(s, &msg, 0)) == -1) {
if (errno == EINTR)
goto again; /* SIGCHLD from server exiting could interrupt */
perror("recvmsg");
exit(1);
}
cmsg = CMSG_FIRSTHDR(&msg);
while (cmsg) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(int) * 2)) {
fd1 = ((int *)CMSG_DATA(cmsg))[0];
fd2 = ((int *)CMSG_DATA(cmsg))[1];
}
cmsg = CMSG_NXTHDR(&msg, cmsg);
}
if (fd1 != -1) write(fd1, "Yeah 1\n", 8);
if (fd2 != -1) write(fd2, "Yeah 2\n", 8);
}
int main (int argc, char **argv)
{
int pid, status;
CLOSE_INHERITED_FDS;
pid = getpid();
sprintf(filea, "/tmp/data1.%d", pid);
sprintf(fileb, "/tmp/data2.%d", pid);
sprintf(sock, "/tmp/sock.%d", pid);
if ((pid = fork()) == 0) {
server();
return 0;
}
client();
wait(&status);
DO( unlink(filea) );
DO( unlink(fileb) );
DO( unlink(sock) );
return 0;
}