/* * 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; }
/* * Author, Copyright: Oleg Borodin <onborodin@gmail.com> */ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/un.h> #include <string.h> #include <err.h> int recvfd (int sock) { 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; if (recvmsg(sock, &msg, 0) == -1) { return -1; } if ((msg.msg_flags & MSG_TRUNC) || (msg.msg_flags & MSG_CTRUNC)) { return -1; } for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { int fd = *(int*)CMSG_DATA(cmsg); return fd; } } return -1; } int main(int argc, char **argv) { //const char sockpath[] = "unix-socket"; char* sockpath = argv[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); unlink(sockpath); socklen_t socklen = sizeof(struct sockaddr_un); if (bind(sock, (struct sockaddr*)paddr, socklen) < 0) { fprintf(stderr, "unable bind unix socket, exit\n"); close(sock); exit(1); } int backlog = 1024; if (listen(sock, backlog) < 0) { fprintf(stderr, "unable listen unix socket, exit\n"); close(sock); exit(1); } fprintf(stderr, "do accept with socket %d\n", sock); while (1) { int fd = -1; if ((fd = recvfd(sock)) > 0) { write(fd, "hello\n", 6); close(fd); } } close(sock); unlink(sockpath); return 0; }
[<>]