1 /* $OpenBSD: PassFd.xs,v 1.2 2014/07/11 22:28:51 bluhm Exp $ */ 2 3 /* 4 * Copyright (c) 2014 Alexander Bluhm <bluhm@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "EXTERN.h" 20 #include "perl.h" 21 #include "XSUB.h" 22 23 #include <sys/socket.h> 24 25 MODULE = PassFd PACKAGE = PassFd 26 27 SV * 28 sendfd(PerlIO *so, PerlIO *fh) 29 PREINIT: 30 int s, fd; 31 struct msghdr msg; 32 struct cmsghdr *cmsg; 33 union { 34 struct cmsghdr hdr; 35 unsigned char buf[CMSG_SPACE(sizeof(int))]; 36 } cmsgbuf; 37 CODE: 38 s = PerlIO_fileno(so); 39 fd = PerlIO_fileno(fh); 40 41 memset(&msg, 0, sizeof(msg)); 42 msg.msg_control = &cmsgbuf.buf; 43 msg.msg_controllen = sizeof(cmsgbuf.buf); 44 45 cmsg = CMSG_FIRSTHDR(&msg); 46 cmsg->cmsg_len = CMSG_LEN(sizeof(int)); 47 cmsg->cmsg_level = SOL_SOCKET; 48 cmsg->cmsg_type = SCM_RIGHTS; 49 *(int *)CMSG_DATA(cmsg) = fd; 50 51 if (sendmsg(s, &msg, 0) == -1) 52 XSRETURN_UNDEF; 53 RETVAL = &PL_sv_yes; 54 OUTPUT: 55 RETVAL 56 57 PerlIO * 58 recvfd(PerlIO *so) 59 PREINIT: 60 PerlIO *fh = NULL; 61 int s, fd; 62 struct msghdr msg; 63 struct cmsghdr *cmsg; 64 union { 65 struct cmsghdr hdr; 66 unsigned char buf[CMSG_SPACE(sizeof(int))]; 67 } cmsgbuf; 68 CODE: 69 s = PerlIO_fileno(so); 70 71 memset(&msg, 0, sizeof(msg)); 72 msg.msg_control = &cmsgbuf.buf; 73 msg.msg_controllen = sizeof(cmsgbuf.buf); 74 75 if (recvmsg(s, &msg, 0) == -1) 76 XSRETURN_UNDEF; 77 if ((msg.msg_flags & MSG_TRUNC) || (msg.msg_flags & MSG_CTRUNC)) { 78 errno = EMSGSIZE; 79 XSRETURN_UNDEF; 80 } 81 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 82 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 83 if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && 84 cmsg->cmsg_level == SOL_SOCKET && 85 cmsg->cmsg_type == SCM_RIGHTS) { 86 fd = *(int *)CMSG_DATA(cmsg); 87 if ((fh = PerlIO_fdopen(fd, "r+")) == NULL) 88 XSRETURN_UNDEF; 89 RETVAL = fh; 90 break; 91 } 92 } 93 if (fh == NULL) { 94 errno = ESRCH; 95 XSRETURN_UNDEF; 96 } 97 OUTPUT: 98 RETVAL 99