diff options
Diffstat (limited to 'vtest/vtest_server.c')
-rw-r--r-- | vtest/vtest_server.c | 277 |
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 } |