3 * Copyright 2008 Free Software Foundation, Inc.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <open_usrp2_socket.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
30 static const char *helper = "usrp2_socket_opener";
33 read_fd(int fd, void *ptr, size_t nbytes, int *recvfd)
39 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
42 char control[CMSG_SPACE(sizeof (int))];
44 struct cmsghdr *cmptr;
46 msg.msg_control = control_un.control;
47 msg.msg_controllen = sizeof(control_un.control);
51 msg.msg_accrights = (char *) &newfd;
52 msg.msg_accrightslen = sizeof(int);
58 iov[0].iov_base = ptr;
59 iov[0].iov_len = nbytes;
63 if ((n = recvmsg(fd, &msg, 0)) <= 0)
66 #ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
67 if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL
68 && cmptr->cmsg_len == CMSG_LEN(sizeof(int))){
69 if (cmptr->cmsg_level != SOL_SOCKET){
70 fprintf(stderr, "read_fd: control level != SOL_SOCKET\n");
73 if (cmptr->cmsg_type != SCM_RIGHTS){
74 fprintf(stderr, "read_fd: control type != SCM_RIGHTS\n");
77 *recvfd = *((int *) CMSG_DATA(cmptr));
79 *recvfd = -1; /* descriptor was not passed */
81 if (msg.msg_accrightslen == sizeof(int))
84 *recvfd = -1; /* descriptor was not passed */
91 usrp2::open_usrp2_socket()
93 int fd = -1, sockfd[2], status;
95 char c, argsockfd[10];
97 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd) != 0){
102 if ((childpid = fork()) == 0) { /* child process */
104 snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]);
105 execlp(helper, helper, argsockfd, (char *) NULL);
106 std::string msg("execlp: couldn't exec " + std::string(helper));
113 /* parent process - wait for the child to terminate */
114 close(sockfd[1]); /* close the end we don't use */
116 waitpid(childpid, &status, 0);
117 if (!WIFEXITED(status)){
118 fprintf(stderr, "child did not terminate\n");
121 if ((status = WEXITSTATUS(status)) == 0)
122 read_fd(sockfd[0], &c, 1, &fd);
124 errno = status; /* bogus: set errno value from child's status */