diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-06-11 17:30:25 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-06-11 17:30:25 +0300 |
commit | 07e7ee3d732b60e0b7f5b242bbfb0cdec8e99e7f (patch) | |
tree | d8106ba7d4e4e92f4bb4f49427eb6e2db10897a3 | |
parent | bf6506cdc46446eada5090a428c2407ebd17468a (diff) | |
download | pies-07e7ee3d732b60e0b7f5b242bbfb0cdec8e99e7f.tar.gz pies-07e7ee3d732b60e0b7f5b242bbfb0cdec8e99e7f.tar.bz2 |
Test pass-fd components
* tests/recvfd.c: New source.
* tests/.gitignore: Update.
* tests/passfd.at: New test.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Add new test.
* tests/nt.c: Check all revents bits.
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/nt.c | 10 | ||||
-rw-r--r-- | tests/passfd.at | 57 | ||||
-rw-r--r-- | tests/recvfd.c | 223 | ||||
-rw-r--r-- | tests/testsuite.at | 1 | ||||
-rw-r--r-- | tests/to.c | 16 |
7 files changed, 305 insertions, 6 deletions
diff --git a/tests/.gitignore b/tests/.gitignore index 68159e3..7d2613a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -8,3 +8,4 @@ testsuite.dir testsuite.log to nt +recvfd diff --git a/tests/Makefile.am b/tests/Makefile.am index fa1d6be..1fe78dc 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -55,6 +55,7 @@ TESTSUITE_AT = \ envop.at\ inet.at\ maxinst.at\ + passfd.at\ respawn.at\ redirect.at\ ret-exec.at\ @@ -67,7 +68,7 @@ TESTSUITE_AT = \ TESTSUITE = $(srcdir)/testsuite M4=m4 -noinst_PROGRAMS = envtest to lines nt +noinst_PROGRAMS = envtest to lines nt recvfd nt_SOURCES = nt.c iobuf.h AM_CPPFLAGS = \ -I$(top_srcdir)/lib\ @@ -1,4 +1,4 @@ -/* This file is part of GNU Pies. +/* This file is part of GNU Pies testsuite. Copyright (C) 2019 Sergey Poznyakoff GNU Pies is free software; you can redistribute it and/or modify @@ -272,15 +272,15 @@ netcat (char const *urlstr) & (srv->state | ((srv->state & POLLOUT) ? POLLHUP : 0))); if (events) { + if (events & POLLIN) + netcat_stream_read (srv); + if (events & POLLOUT) + netcat_stream_write (srv); if (events & POLLHUP) { //grecs_error (NULL, 0, "HUP on %s", srv->id); netcat_stream_disconnect (srv, srv->state); } - else if (events & POLLIN) - netcat_stream_read (srv); - else if (events & POLLOUT) - netcat_stream_write (srv); } if (srv->state == 0 || srv->pollfd->fd == -1) netcat_server_remove (srv); diff --git a/tests/passfd.at b/tests/passfd.at new file mode 100644 index 0000000..4a685a3 --- /dev/null +++ b/tests/passfd.at @@ -0,0 +1,57 @@ +# This file is part of GNU pies testsuite. -*- Autotest -*- +# Copyright (C) 2016-2019 Sergey Poznyakoff +# +# GNU pies 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, or (at your option) +# any later version. +# +# GNU pies 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 GNU pies. If not, see <http://www.gnu.org/licenses/>. +AT_SETUP([pass-fd component]) +AT_CHECK([ +PIES_XFAIL_CHECK +PIES_CONTROL_INIT + +AT_DATA([input], +[now is +the time +stop +]) + +: ${PIES_TEST_INET_SOCKET:=unix://$PWD/in.sock} +PIES_FD_SOCKET=$PWD/pfd.sock + +cat > pies.conf <<_EOT +component pfd { + command "recvfd '$PIES_FD_SOCKET' $auxdir/in.test $PWD/inlog"; + mode pass-fd; + pass-fd-timeout 3; + pass-fd-socket "$PIES_FD_SOCKET"; + socket "$PIES_TEST_INET_SOCKET"; + stderr file "$PWD/log.err"; +} +component controller { + command "nt $PIES_TEST_INET_SOCKET -i input"; +} +_EOT + +set -e +to 10 \ + pies --foreground --stderr \ + --config-file control.conf --config-file pies.conf --debug 1 2>errlog + +cat inlog +cat log.err >&2 +], +[0], +[now is +the time +stop +]) +AT_CLEANUP
\ No newline at end of file diff --git a/tests/recvfd.c b/tests/recvfd.c new file mode 100644 index 0000000..82455c7 --- /dev/null +++ b/tests/recvfd.c @@ -0,0 +1,223 @@ +/* This file is part of GNU Pies testsuite. + Copyright (C) 2019 Sergey Poznyakoff + + GNU Pies 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, or (at your option) + any later version. + + GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <signal.h> +#include "libpies.h" + +char const *progname; + +void +usage (void) +{ + fprintf (stderr, "usage: %s SOCKET COMMAND ARGS...\n", progname); + fprintf (stderr, "Test tool for pass-fd pies components.\n"); + fprintf (stderr, "Listens on the file descriptor obtained from SOCKET.\n"); + fprintf (stderr, "For each connection, execs COMMAND ARGS as a separate process.\n"); + exit (64); +} + +static int +listen_socket (char const *socket_name) +{ + struct sockaddr_un addr; + int sockfd; + + if (strlen (socket_name) > sizeof addr.sun_path) + { + fprintf (stderr, "%s: UNIX socket name too long\n", progname); + return -1; + } + addr.sun_family = AF_UNIX; + strcpy (addr.sun_path, socket_name); + + sockfd = socket (PF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) + { + perror ("socket"); + exit (1); + } + + umask (0117); + if (bind (sockfd, (struct sockaddr *) &addr, sizeof (addr)) < 0) + { + perror ("bind"); + exit (1); + } + + if (listen (sockfd, 8) < 0) + { + perror ("listen"); + exit (1); + } + return sockfd; +} + +static int +read_fd (int fd) +{ + struct msghdr msg; + struct iovec iov[1]; + char base[1]; + +#if HAVE_STRUCT_MSGHDR_MSG_CONTROL + union + { + struct cmsghdr cm; + char control[CMSG_SPACE (sizeof (int))]; + } control_un; + struct cmsghdr *cmptr; + + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof (control_un.control); +#elif HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS + int newfd; + + msg.msg_accrights = (caddr_t) &newfd; + msg.msg_accrightslen = sizeof (int); +#else + fprintf (stderr, "no way to get fd\n"); + exit (77); +#endif + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + iov[0].iov_base = base; + iov[0].iov_len = sizeof (base); + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + if (recvmsg (fd, &msg, 0) > 0) + { +#if HAVE_STRUCT_MSGHDR_MSG_CONTROL + if ((cmptr = CMSG_FIRSTHDR (&msg)) != NULL + && cmptr->cmsg_len == CMSG_LEN (sizeof (int)) + && cmptr->cmsg_level == SOL_SOCKET + && cmptr->cmsg_type == SCM_RIGHTS) + return *((int*) CMSG_DATA (cmptr)); +#elif HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS + if (msg.msg_accrightslen == sizeof (int)) + return newfd; +#endif + } + return -1; +} + +static int +get_fd (int lfd) +{ + int sfd, fd = accept (lfd, NULL, NULL); + if (fd == -1) + { + perror ("accept"); + exit (1); + } + + sfd = read_fd (fd); + close (fd); + return sfd; +} + +static void +sigchld (int sig) +{ + pid_t pid; + + while ((pid = waitpid ((pid_t)-1, NULL, WNOHANG)) >= 0) + ; + signal (sig, sigchld); +} + +static void +sigquit (int sig) +{ + kill (0, sig); + exit (0); +} + +int +main (int argc, char **argv) +{ + int sfd, fd; + + progname = argv[0]; + + if (argc < 3) + usage (); + + sfd = listen_socket (argv[1]); + + argc -= 2; + argv += 2; + + fd = get_fd (sfd); + close (sfd); + + signal (SIGCHLD, sigchld); + signal (SIGTERM, sigquit); + signal (SIGHUP, sigquit); + signal (SIGINT, sigquit); + signal (SIGQUIT, sigquit); + + while (1) + { + int cfd = accept (fd, NULL, NULL); + if (cfd == -1) + { + perror ("accept"); + exit (1); + } + + pid_t pid = fork (); + if (pid == 0) + { + int i; + + for (i = getmaxfd (); i >= 0; i--) + if (i != cfd) + close (i); + + if (cfd != 0) + dup2 (cfd, 0); + if (cfd != 1) + dup2 (cfd, 1); + if (cfd != 2) + dup2 (cfd, 2); + if (cfd > 2) + close (cfd); + + execvp (argv[0], argv); + exit (127); + } + if (pid == -1) + { + perror ("fork"); + } + close (cfd); + } + return 0; +} diff --git a/tests/testsuite.at b/tests/testsuite.at index 0682b51..843d235 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -71,6 +71,7 @@ m4_include([shutdown.at]) m4_include([shell.at]) m4_include([inet.at]) m4_include([maxinst.at]) +m4_include([passfd.at]) m4_include([envop.at]) m4_include([env.at])
\ No newline at end of file @@ -1,3 +1,19 @@ +/* This file is part of GNU Pies testsuite. + Copyright (C) 2019 Sergey Poznyakoff + + GNU Pies 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, or (at your option) + any later version. + + GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */ + #include <config.h> #include <stdlib.h> #include <stdio.h> |