summaryrefslogtreecommitdiff
path: root/vtest/vtest_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'vtest/vtest_server.c')
-rw-r--r--vtest/vtest_server.c277
1 files changed, 176 insertions, 101 deletions
diff --git a/vtest/vtest_server.c b/vtest/vtest_server.c
index 578c4740..4234de17 100644
--- a/vtest/vtest_server.c
+++ b/vtest/vtest_server.c
@@ -21,7 +21,6 @@
* OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
-
#include <stdio.h>
#include <signal.h>
#include <stdbool.h>
@@ -39,55 +38,195 @@
#include "vtest_protocol.h"
-static int vtest_open_socket(const char *path)
+
+struct vtest_program
+{
+ const char *socket_name;
+ int socket;
+ const char *read_file;
+ int out_fd;
+ int in_fd;
+
+ bool do_fork;
+ bool loop;
+};
+
+struct vtest_program prog = {
+ .socket_name = VTEST_DEFAULT_SOCKET_NAME,
+ .socket = -1,
+
+ .read_file = NULL,
+
+ .in_fd = -1,
+ .out_fd = -1,
+ .do_fork = true,
+ .loop = true,
+};
+
+static void vtest_main_parse_args(int argc, char **argv);
+static void vtest_main_set_signal(void);
+static void vtest_main_open_read_file(void);
+static void vtest_main_open_socket(void);
+static void vtest_main_run_renderer(int in_fd, int out_fd);
+static void vtest_main_wait_for_socket_accept(void);
+static void vtest_main_tidy_fds(void);
+static void vtest_main_close_socket(void);
+
+
+int main(int argc, char **argv)
+{
+#ifdef __AFL_LOOP
+while (__AFL_LOOP(1000)) {
+#endif
+
+ vtest_main_parse_args(argc, argv);
+
+ if (prog.read_file != NULL) {
+ vtest_main_open_read_file();
+ goto start;
+ }
+
+ if (prog.do_fork) {
+ vtest_main_set_signal();
+ }
+
+ vtest_main_open_socket();
+restart:
+ vtest_main_wait_for_socket_accept();
+
+start:
+ if (prog.do_fork) {
+ /* fork a renderer process */
+ if (fork() == 0) {
+ vtest_main_run_renderer(prog.in_fd, prog.out_fd);
+ exit(0);
+ }
+ } else {
+ vtest_main_run_renderer(prog.in_fd, prog.out_fd);
+ }
+
+ vtest_main_tidy_fds();
+
+ if (prog.loop) {
+ goto restart;
+ }
+
+ vtest_main_close_socket();
+
+#ifdef __AFL_LOOP
+}
+#endif
+}
+
+static void vtest_main_parse_args(int argc, char **argv)
+{
+ if (argc > 1) {
+ if (!strcmp(argv[1], "--no-loop-or-fork")) {
+ prog.do_fork = false;
+ prog.loop = false;
+ } else if (!strcmp(argv[1], "--no-fork")) {
+ prog.do_fork = false;
+ } else {
+ prog.read_file = argv[1];
+ prog.loop = false;
+ prog.do_fork = false;
+ }
+ }
+}
+
+static void vtest_main_set_signal(void)
+{
+ struct sigaction sa;
+ int ret;
+
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ ret = sigaction(SIGCHLD, &sa, 0);
+ if (ret == -1) {
+ perror(NULL);
+ exit(1);
+ }
+}
+
+static void vtest_main_open_read_file(void)
+{
+ int ret;
+
+ ret = open(prog.read_file, O_RDONLY);
+ if (ret == -1) {
+ perror(NULL);
+ exit(1);
+ }
+ prog.in_fd = ret;
+
+ ret = open("/dev/null", O_WRONLY);
+ if (ret == -1) {
+ perror(NULL);
+ exit(1);
+ }
+ prog.out_fd = ret;
+}
+
+static void vtest_main_open_socket(void)
{
struct sockaddr_un un;
- int sock;
- sock = socket(PF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- return -1;
+ prog.socket = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (prog.socket < 0) {
+ goto err;
}
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
- snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
+ snprintf(un.sun_path, sizeof(un.sun_path), "%s", prog.socket_name);
unlink(un.sun_path);
- if (bind(sock, (struct sockaddr *)&un, sizeof(un)) < 0) {
+ if (bind(prog.socket, (struct sockaddr *)&un, sizeof(un)) < 0) {
goto err;
}
- if (listen(sock, 1) < 0){
+ if (listen(prog.socket, 1) < 0){
goto err;
}
- return sock;
+ return;
+
err:
- close(sock);
- return -1;
+ perror("Failed to setup socket.");
+ exit(1);
}
-static int wait_for_socket_accept(int sock)
+static void vtest_main_wait_for_socket_accept(void)
{
fd_set read_fds;
int new_fd;
int ret;
FD_ZERO(&read_fds);
- FD_SET(sock, &read_fds);
+ FD_SET(prog.socket, &read_fds);
- ret = select(sock + 1, &read_fds, NULL, NULL, NULL);
+ ret = select(prog.socket + 1, &read_fds, NULL, NULL, NULL);
if (ret < 0) {
- return ret;
+ perror("Failed to select on socket!");
+ exit(1);
+ }
+
+ if (!FD_ISSET(prog.socket, &read_fds)) {
+ perror("Odd state in fd_set.");
+ exit(1);
}
- if (FD_ISSET(sock, &read_fds)) {
- new_fd = accept(sock, NULL, NULL);
- return new_fd;
+ new_fd = accept(prog.socket, NULL, NULL);
+ if (new_fd < 0) {
+ perror("Failed to accept socket.");
+ exit(1);
}
- return -1;
+
+ prog.in_fd = new_fd;
+ prog.out_fd = new_fd;
}
typedef int (*vtest_cmd_fptr_t)(uint32_t);
@@ -110,7 +249,7 @@ static const vtest_cmd_fptr_t vtest_commands[] = {
vtest_transfer_put2,
};
-static int run_renderer(int in_fd, int out_fd)
+static void vtest_main_run_renderer(int in_fd, int out_fd)
{
int err, ret;
uint32_t header[VTEST_HDR_SIZE];
@@ -164,94 +303,30 @@ static int run_renderer(int in_fd, int out_fd)
fprintf(stderr, "socket failed (%d) - closing renderer\n", err);
vtest_destroy_renderer();
- close(in_fd);
-
- return 0;
}
-int main(int argc, char **argv)
+static void vtest_main_tidy_fds(void)
{
- int ret, sock = -1, in_fd, out_fd;
- pid_t pid;
- bool do_fork = true, loop = true;
- struct sigaction sa;
- char *socket_name = VTEST_DEFAULT_SOCKET_NAME;
-
-#ifdef __AFL_LOOP
-while (__AFL_LOOP(1000)) {
-#endif
-
- if (argc > 1) {
- if (!strcmp(argv[1], "--no-loop-or-fork")) {
- do_fork = false;
- loop = false;
- } else if (!strcmp(argv[1], "--no-fork")) {
- do_fork = false;
- } else {
- ret = open(argv[1], O_RDONLY);
- if (ret == -1) {
- perror(0);
- exit(1);
- }
- in_fd = ret;
- ret = open("/dev/null", O_WRONLY);
- if (ret == -1) {
- perror(0);
- exit(1);
- }
- out_fd = ret;
- loop = false;
- do_fork = false;
- goto start;
- }
+ // out_fd will be closed by the in_fd clause if they are the same.
+ if (prog.out_fd == prog.in_fd) {
+ prog.out_fd = -1;
}
- if (do_fork) {
- sa.sa_handler = SIG_IGN;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- if (sigaction(SIGCHLD, &sa, 0) == -1) {
- perror(0);
- exit(1);
- }
+ if (prog.in_fd != -1) {
+ close(prog.in_fd);
+ prog.in_fd = -1;
}
- sock = vtest_open_socket(socket_name);
-restart:
- in_fd = wait_for_socket_accept(sock);
- out_fd = in_fd;
-
-start:
- if (do_fork) {
- /* fork a renderer process */
- switch ((pid = fork())) {
- case 0:
- run_renderer(in_fd, out_fd);
- exit(0);
- break;
- case -1:
- default:
- close(in_fd);
- if (loop) {
- goto restart;
- }
- }
- } else {
- run_renderer(in_fd, out_fd);
- vtest_destroy_renderer();
- if (loop) {
- goto restart;
- }
+ if (prog.out_fd != -1) {
+ close(prog.out_fd);
+ prog.out_fd = -1;
}
+}
- if (sock != -1) {
- close(sock);
- }
- if (in_fd != out_fd) {
- close(out_fd);
+static void vtest_main_close_socket(void)
+{
+ if (prog.socket != -1) {
+ close(prog.socket);
+ prog.socket = -1;
}
-
-#ifdef __AFL_LOOP
-}
-#endif
}