From adc8af1a3a0d9077621d2b9b5e36b33452f31947 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 5 Sep 2015 00:54:42 -0600 Subject: Add a minimal systemd-like runner for testing --- test/.gitignore | 1 + test/runner.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 test/.gitignore create mode 100644 test/runner.c (limited to 'test') diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..09230a9 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +/runner diff --git a/test/runner.c b/test/runner.c new file mode 100644 index 0000000..82b8d6e --- /dev/null +++ b/test/runner.c @@ -0,0 +1,146 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _(s) s + +const char *xgetenv(const char *name, const char *unset) { + const char *val = getenv(name); + if (!val) + val = unset; + return val; +} + +char *xasprintf(const char *format, ...) { + va_list arg; + int len; + char *str = NULL; + + va_start(arg, format); + len = vasprintf(&str, format, arg); + va_end(arg); + + if (len < 0) + error(EXIT_FAILURE, errno, _("Could not allocate memory in vasprintf")); + + return str; +} + +#define xasprintfa(...) (__extension__ ({ char *heap = xasprintf(__VA_ARGS__); char *stack = strdupa(heap); free(heap); stack; })) + +int pid = -1; +void +sigchld_handler(int sig __attribute__((__unused__))) { + int status; + pid = waitpid(pid, &status, WNOHANG); + int exited = WEXITSTATUS(status); + error(exited, 0, "%ld exited with status %d", (long)pid, exited); + exit(0); +} + +union addr { + struct sockaddr gen; + struct sockaddr_un un; +}; + +int new_unix_sock(const char *filename, int type) { + union addr addr; + addr.un.sun_family = AF_UNIX; + strcpy(addr.un.sun_path, filename); + + int sock = socket(AF_UNIX, type, 0); + if (sock < 0) + error(EXIT_FAILURE, errno, "socket(%d, %d)", AF_UNIX, type); + unlink(filename); + if (bind(sock, &addr.gen, sizeof(addr))) + error(EXIT_FAILURE, errno, "bind(%d, sockaddr(\"%s\"))", sock, filename); + switch (type) { + case SOCK_STREAM: + case SOCK_SEQPACKET: + if (listen(sock, 5)) + error(EXIT_FAILURE, errno, "listen(%d /* \"%s\" */, %d)", sock, filename, 5); + break; + case SOCK_DGRAM: + break; + default: + error(EXIT_FAILURE, errno, "new_unix_sock: Unrecognized type: %d", type); + } + return sock; +} + +char *cmdname = "nshd_runner"; +const char *notify_sockname = "notify.sock"; +const char *nslcd_sockname = "nslcd.sock"; +void cleanup(void) { + if (nslcd_sockname) + unlink(nslcd_sockname); + if (notify_sockname) + unlink(notify_sockname); + fprintf(stderr, "%s: Exiting\n", cmdname); +} + +int main(int argc, char *argv[]) { + cmdname = argv[0]; + if (argc != 2) { + error(2, 0, _("Usage: %s NSHD_PROGRAM"), argv[0]); + } + + atexit(&cleanup); + int nslcd_sock = new_unix_sock(nslcd_sockname , SOCK_STREAM); + int notify_sock = new_unix_sock(notify_sockname, SOCK_DGRAM ); + + struct sigaction act; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = sigchld_handler; + if (sigaction(SIGCHLD, &act, 0)) + error(EXIT_FAILURE, errno, "sigaction"); + + + pid = fork(); + switch (pid) { + case -1: + error(EXIT_FAILURE, errno, "fork"); + case 0: + close(notify_sock); + dup2(nslcd_sock, 3); + if (nslcd_sock != 3) + close(nslcd_sock); + pid = getpid(); + setenv("LISTEN_PID", xasprintfa("%ld", (long)pid), 1); + setenv("LISTEN_FDS", "1", 1); + execl(argv[1], argv[1], NULL); + error(EXIT_FAILURE, errno, "execl"); + } + + while (1) { + union addr client_addr; + socklen_t client_size; + char buf[4096]; + ssize_t bytes_read = recvfrom(notify_sock, buf, sizeof(buf), 0, &client_addr.gen, &client_size); + if (bytes_read < 1) + error(EXIT_FAILURE, errno, "recvfrom"); + ssize_t bytes_written = 0; + while (bytes_written < bytes_read) { + ssize_t n = write(2, &(buf[bytes_written]), bytes_read-bytes_written); + if (n < 0) { + bytes_written = -1; + break; + } + bytes_written += n; + } + if (bytes_written < 0) + error(EXIT_FAILURE, errno, "write"); + } + + return 0; +} -- cgit v1.2.2