/*
* Author, Copyright: Oleg Borodin <onborodin@gmail.com>
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
ssize_t sendfd(int sock, int fd) {
struct msghdr msg;
struct cmsghdr* cmsg;
union {
struct cmsghdr hdr;
unsigned char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf;
struct iovec iov[1];
char ch = '*';
iov[0].iov_base = &ch;
iov[0].iov_len = 1;
memset(&msg, 0, sizeof(msg));
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int*)CMSG_DATA(cmsg) = fd;
ssize_t res = -1;
res = sendmsg(sock, &msg, 0);
return res;
}
int main(int argc, char **argv) {
char sockpath[] = "/tmp/unix-socket";
pid_t pid = fork();
if (pid == 0){
/* into the child */
char subserv[] = "./subserv";
char* args[] = { subserv, sockpath, NULL };
int res = execv(subserv, args);
fprintf(stderr, "exec res %d\n", res);
}
if (pid < 0) {
fprintf(stderr, "unable fork, exit\n");
exit(1);
}
int sock = -1;
if((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "unable create unix socket, exit\n");
exit(1);
}
struct sockaddr sockaddr;
memset(&sockaddr, 0, sizeof(struct sockaddr));
struct sockaddr_un* paddr = (struct sockaddr_un*)&sockaddr;
paddr->sun_family = AF_UNIX;
strcpy(paddr->sun_path, sockpath);
socklen_t socklen = sizeof(struct sockaddr_un);
sleep(1);
if (connect(sock, (struct sockaddr*)&sockaddr, socklen) < 0) {
fprintf(stderr, "unable connect to unix socket, exit.\n");
exit(1);
}
fprintf(stderr, "connect to unix socket %d\n", sock);
int fd = -1;
if ((fd = open("test.txt", O_RDWR | O_APPEND | O_CREAT, 0644)) < 0) {
fprintf(stderr, "unable open file, exit.\n");
exit(1);
}
while(true) {
ssize_t res = sendfd(sock, fd);
fprintf(stderr, "send %d chars\n", (int)res);
sleep(1);
}
close(fd);
close(sock);
kill(pid, SIGTERM);
int status;
waitpid(pid, &status, 0);
return 0;
}