Add simple testing for passfd --- lib/passfd.c | 134 ++++++++++++++++++++++++++------------------------- lib/passfd.h | 7 +-- tests/test-passfd.c | 108 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 70 deletions(-) create mode 100644 tests/test-passfd.c
diff --git a/lib/passfd.c b/lib/passfd.c index fc8965f..6ec495b 100644 --- a/lib/passfd.c +++ b/lib/passfd.c @@ -37,7 +37,8 @@ return -1 in case of error, 0 on success */ -int sendfd(int sock, int fd) +int +sendfd (int sock, int fd) { char send = 0; struct iovec iov[1]; @@ -45,36 +46,36 @@ int sendfd(int sock, int fd) /* send at least one char */ iov[0].iov_base = &send; - iov[0].iov_len = 1; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_name = 0; + iov[0].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = 0; msg.msg_namelen = 0; - + { #ifdef HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44 - struct cmsghdr *cmsg; - char buf[CMSG_SPACE(sizeof(fd))]; - - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - /* Initialize the payload: */ - (*(int *) CMSG_DATA(cmsg)) = fd; - msg.msg_controllen = cmsg->cmsg_len; + struct cmsghdr *cmsg; + char buf[CMSG_SPACE (sizeof (fd))]; + + msg.msg_control = buf; + msg.msg_controllen = sizeof (buf); + cmsg = CMSG_FIRSTHDR (&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof (int)); + /* Initialize the payload: */ + (*(int *) CMSG_DATA (cmsg)) = fd; + msg.msg_controllen = cmsg->cmsg_len; #elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43 - msg.msg_accrights = &fd; - msg.msg_accrightslen = sizeof(fd); + msg.msg_accrights = &fd; + msg.msg_accrightslen = sizeof (fd); #else - errno = ENOSYS; - return -1; -#endif + errno = ENOSYS; + return -1; +#endif } - - if(sendmsg(sock, &msg, 0) != iov[0].iov_len) + + if (sendmsg (sock, &msg, 0) != iov[0].iov_len) return -1; return 0; } @@ -84,7 +85,8 @@ int sendfd(int sock, int fd) return -1 in case of error, fd on success */ -int recvfd(int sock) +int +recvfd (int sock) { char recv = 0; int fd; @@ -93,51 +95,51 @@ int recvfd(int sock) /* send at least one char */ iov[0].iov_base = &recv; - iov[0].iov_len = 1; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_name = 0; + iov[0].iov_len = 1; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = 0; msg.msg_namelen = 0; { #ifdef HAVE_UNIXSOCKET_SCM_RIGHTS_BSD44 - struct cmsghdr *cmsg; - char buf[CMSG_SPACE(sizeof(fd))]; - - msg.msg_control = buf; - msg.msg_controllen = sizeof(buf); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - /* Initialize the payload: */ - (*(int *) CMSG_DATA(cmsg)) = -1; - msg.msg_controllen = cmsg->cmsg_len; - - if(recvmsg(sock, &msg, 0) < 0) - return -1; - - cmsg = CMSG_FIRSTHDR(&msg); - /* be paranoiac */ - if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN(sizeof(int)) - || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) - { - /* fake errno: at end the file is not available */ - errno = EACCES; - return -1; - } - - fd = *(int*)CMSG_DATA(cmsg); - return fd; + struct cmsghdr *cmsg; + char buf[CMSG_SPACE (sizeof (fd))]; + + msg.msg_control = buf; + msg.msg_controllen = sizeof (buf); + cmsg = CMSG_FIRSTHDR (&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof (int)); + /* Initialize the payload: */ + (*(int *) CMSG_DATA (cmsg)) = -1; + msg.msg_controllen = cmsg->cmsg_len; + + if (recvmsg (sock, &msg, 0) < 0) + return -1; + + cmsg = CMSG_FIRSTHDR (&msg); + /* be paranoiac */ + if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof (int)) + || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) + { + /* fake errno: at end the file is not available */ + errno = EACCES; + return -1; + } + + fd = *(int *) CMSG_DATA (cmsg); + return fd; #elif HAVE_UNIXSOCKET_SCM_RIGHTS_BSD43 - msg.msg_accrights = &fd; - msg.msg_accrightslen = sizeof(fd); - if(recvmsg(sock, &msg, 0) < 0) - return -1; - return fd; + msg.msg_accrights = &fd; + msg.msg_accrightslen = sizeof (fd); + if (recvmsg (sock, &msg, 0) < 0) + return -1; + return fd; #else - errno = ENOSYS; - return -1; -#endif + errno = ENOSYS; + return -1; +#endif } } diff --git a/lib/passfd.h b/lib/passfd.h index 4d0bfab..13eb3b1 100644 --- a/lib/passfd.h +++ b/lib/passfd.h @@ -15,8 +15,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef PASSFD_H_ -# define PASSFD_H_ 1 -int sendfd(int sock, int fd); -int recvfd(int sock); +#define PASSFD_H_ 1 +int sendfd (int sock, int fd); +int recvfd (int sock); #endif - diff --git a/tests/test-passfd.c b/tests/test-passfd.c new file mode 100644 index 0000000..3976316 --- /dev/null +++ b/tests/test-passfd.c @@ -0,0 +1,108 @@ +/* Test of terminating the current process. + Copyright (C) 2010-2011 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include "passfd.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <fcntl.h> + + +#include "macros.h" + +int +main () +{ + int pair[2]; + int ret; + pid_t pid; + int status; + int fdnull; + int fd; + struct stat st; + + fdnull = open ("/dev/null", O_RDWR); + if (fdnull < 0) + { + perror ("Could not open /dev/null"); + return 1; + } + + ret = socketpair (AF_UNIX, SOCK_STREAM, 0, pair); + if (ret < 0) + { + perror ("socket pair failled"); + return 2; + } + + pid = fork (); + if (pid == -1) + { + perror ("fork:"); + return 3; + } + if (pid == 0) + { + ret = sendfd (pair[1], fdnull); + if (ret == -1) + { + perror ("sendfd:"); + return 64; + } + sleep (10); + return 0; + } + /* father */ + else + { + fd = recvfd (pair[0]); + if (fd == -1) + { + perror ("recvfd"); + return 16; + } + ret = waitpid (pid, &status, 0); + if (ret == -1) + { + perror ("waitpid:"); + return 17; + } + ASSERT (ret == pid); + + ret = WIFEXITED (status); + if (ret == 0) + { + fprintf (stderr, "Child does not normally exit\n"); + return 65; + } + ret = WEXITSTATUS (status); + if (ret != 0) + { + fprintf (stderr, "Send fd fail"); + return ret; + } + + /* try to stat new fd */ + ret == fstat (fd, &st); + if (0 == ret) + return 80; + return 0; + } +} -- 1.7.2.3