}
SET_NODATACOW
+# last choice for script/lei, 1st choice for lei internals
+# compatible with PublicInbox::CmdIPC4
my $fdpass = <<'FDPASS';
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/socket.h>
#if defined(CMSG_SPACE) && defined(CMSG_LEN)
-struct my_3fds { int fds[3]; };
+#define SEND_FD_CAPA 6
+#define SEND_FD_SPACE (SEND_FD_CAPA * sizeof(int))
union my_cmsg {
struct cmsghdr hdr;
- char pad[sizeof(struct cmsghdr)+ 8 + sizeof(struct my_3fds) + 8];
+ char pad[sizeof(struct cmsghdr) + 16 + SEND_FD_SPACE];
};
-int send_3fds(int sockfd, int infd, int outfd, int errfd)
+SV *send_cmd4(PerlIO *s, SV *svfds, SV *data, int flags)
{
struct msghdr msg = { 0 };
- struct iovec iov;
union my_cmsg cmsg = { 0 };
+ STRLEN dlen = 0;
+ struct iovec iov;
+ ssize_t sent;
+ AV *fds = (AV *)SvRV(svfds);
+ I32 i, nfds = av_len(fds) + 1;
int *fdp;
- size_t i;
- iov.iov_base = &msg.msg_namelen; /* whatever */
- iov.iov_len = 1;
+ if (SvOK(data)) {
+ iov.iov_base = SvPV(data, dlen);
+ iov.iov_len = dlen;
+ }
+ if (!dlen) { /* must be non-zero */
+ iov.iov_base = &msg.msg_namelen; /* whatever */
+ iov.iov_len = 1;
+ }
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
- msg.msg_control = &cmsg.hdr;
- msg.msg_controllen = CMSG_SPACE(sizeof(struct my_3fds));
-
- cmsg.hdr.cmsg_level = SOL_SOCKET;
- cmsg.hdr.cmsg_type = SCM_RIGHTS;
- cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(struct my_3fds));
- fdp = (int *)CMSG_DATA(&cmsg.hdr);
- *fdp++ = infd;
- *fdp++ = outfd;
- *fdp++ = errfd;
- return sendmsg(sockfd, &msg, 0) >= 0;
+ if (nfds) {
+ if (nfds > SEND_FD_CAPA) {
+ fprintf(stderr, "FIXME: bump SEND_FD_CAPA=%d\n", nfds);
+ nfds = SEND_FD_CAPA;
+ }
+ msg.msg_control = &cmsg.hdr;
+ msg.msg_controllen = CMSG_SPACE(nfds * sizeof(int));
+ cmsg.hdr.cmsg_level = SOL_SOCKET;
+ cmsg.hdr.cmsg_type = SCM_RIGHTS;
+ cmsg.hdr.cmsg_len = CMSG_LEN(nfds * sizeof(int));
+ fdp = (int *)CMSG_DATA(&cmsg.hdr);
+ for (i = 0; i < nfds; i++) {
+ SV **fd = av_fetch(fds, i, 0);
+ *fdp++ = SvIV(*fd);
+ }
+ }
+ sent = sendmsg(PerlIO_fileno(s), &msg, flags);
+ return sent >= 0 ? newSViv(sent) : &PL_sv_undef;
}
-void recv_3fds(int sockfd)
+void recv_cmd4(PerlIO *s, SV *buf, STRLEN n)
{
union my_cmsg cmsg = { 0 };
struct msghdr msg = { 0 };
struct iovec iov;
- size_t i;
+ ssize_t i;
Inline_Stack_Vars;
+ Inline_Stack_Reset;
- iov.iov_base = &msg.msg_namelen; /* whatever */
- iov.iov_len = 1;
+ if (!SvOK(buf))
+ sv_setpvn(buf, "", 0);
+ iov.iov_base = SvGROW(buf, n + 1);
+ iov.iov_len = n;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &cmsg.hdr;
- msg.msg_controllen = CMSG_SPACE(sizeof(struct my_3fds));
-
- if (recvmsg(sockfd, &msg, 0) <= 0)
- return;
-
- errno = EDOM;
- Inline_Stack_Reset;
- if (cmsg.hdr.cmsg_level == SOL_SOCKET &&
- cmsg.hdr.cmsg_type == SCM_RIGHTS &&
- cmsg.hdr.cmsg_len == CMSG_LEN(sizeof(struct my_3fds))) {
+ msg.msg_controllen = CMSG_SPACE(SEND_FD_SPACE);
+
+ i = recvmsg(PerlIO_fileno(s), &msg, 0);
+ if (i < 0)
+ Inline_Stack_Push(&PL_sv_undef);
+ else
+ SvCUR_set(buf, i);
+ if (i > 0 && cmsg.hdr.cmsg_level == SOL_SOCKET &&
+ cmsg.hdr.cmsg_type == SCM_RIGHTS) {
+ size_t len = cmsg.hdr.cmsg_len;
int *fdp = (int *)CMSG_DATA(&cmsg.hdr);
- size_t i;
-
- for (i = 0; i < 3; i++)
+ for (i = 0; CMSG_LEN((i + 1) * sizeof(int)) <= len; i++)
Inline_Stack_Push(sv_2mortal(newSViv(*fdp++)));
}
Inline_Stack_Done;
*nodatacow_fd = \&PublicInbox::NDC_PP::nodatacow_fd;
*nodatacow_dir = \&PublicInbox::NDC_PP::nodatacow_dir;
}
-unless (__PACKAGE__->can('recv_3fds')) {
- eval { # try the XS IO::FDPass package
- require IO::FDPass;
- no warnings 'once';
- *recv_3fds = sub { map { IO::FDPass::recv($_[0]) } (0..2) };
- *send_3fds = sub ($$$$) {
- my $sockfd = shift;
- IO::FDPass::send($sockfd, shift) for (0..2);
- };
- };
-}
undef $set_nodatacow;
undef $vfork_spawn;
sub which ($) {
my ($file) = @_;
return $file if index($file, '/') >= 0;
- foreach my $p (split(':', $ENV{PATH})) {
+ for my $p (split(/:/, $ENV{PATH})) {
$p .= "/$file";
return $p if -x $p;
}