From 1716ec0582013f3b6cadea718a122c092f8c7033 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Tue, 21 Apr 2026 08:40:06 -0500 Subject: [PATCH 01/34] Request -> Peek --- src/actions.c | 2 +- src/actions.h | 2 +- src/args.c | 6 +++--- src/daemon.c | 2 +- src/help.c | 8 ++++---- src/help.h | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/actions.c b/src/actions.c index c554e74..8fd6505 100644 --- a/src/actions.c +++ b/src/actions.c @@ -150,7 +150,7 @@ int testrig_open([[maybe_unused]] other_args* others) { return 0; } -int testrig_request([[maybe_unused]] other_args* others) { +int testrig_peek([[maybe_unused]] other_args* others) { // need to impl a daemon autolaunches struct sockaddr_un sockaddr = { 0 }; diff --git a/src/actions.h b/src/actions.h index 4043c16..c9930ba 100644 --- a/src/actions.h +++ b/src/actions.h @@ -17,7 +17,7 @@ int delegate_to_daemon(enum CLI_ACTION act); int testrig_ident(other_args* others); int testrig_stat(other_args* others); int testrig_open(other_args* others); -int testrig_request(other_args* others); +int testrig_peek(other_args* others); int testrig_close(other_args* others); void free_other_args(other_args* others); diff --git a/src/args.c b/src/args.c index 1ce42cd..ec78285 100644 --- a/src/args.c +++ b/src/args.c @@ -14,10 +14,10 @@ static void die_invalid_arg(const char* arg) { static char* mode_map[] = { "command", "detach" }; char* action_map[] = { "help", "ident", "status", "daemon", - "open", "request", "close" }; + "open", "peek", "close" }; static int(*fun_map[])(other_args*) = { &help_me, &testrig_ident, &testrig_stat, &testrig_daemon, - &testrig_open, &testrig_request, &testrig_close }; + &testrig_open, &testrig_peek, &testrig_close }; int is_flag(const char* arg) { return (strstr(arg, "--") == NULL) ? 0 : 1; } int is_opt(const char* arg) { @@ -49,7 +49,7 @@ int parse_act(const char* act, struct parsed_args* parsed) { else if (!strncmp("ident", act, 6)) { parsed->action = ACTION_IDENT; ret = 1; } else if (!strncmp("status", act, 7)) { parsed->action = ACTION_STAT; ret = 1; } else if (!strncmp("open", act, 5)) { parsed->action = ACTION_OPEN; ret = 1; } - else if (!strncmp("request", act, 7)) { parsed->action = ACTION_REQUEST; ret = 1; } + else if (!strncmp("peek", act, 7)) { parsed->action = ACTION_REQUEST; ret = 1; } else if (!strncmp("close", act, 6)) { parsed->action = ACTION_CLOSE; ret = 1; } else if (!strncmp("help", act, 5)) { parsed->action = ACTION_HELP; ret = 1; } diff --git a/src/daemon.c b/src/daemon.c index bc27d4e..bd0a16a 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -139,7 +139,7 @@ int testrig_daemon([[maybe_unused]] other_args* others) { if (!strncmp("STATUS", body, 7)) { testrig_stat(NULL); } else if (!strncmp("OPEN", body, 5)) { testrig_open(NULL); } - else if (!strncmp("REQUEST", body, 7)) { testrig_request(NULL); } + else if (!strncmp("REQUEST", body, 7)) { testrig_peek(NULL); } else if (!strncmp("CLOSE", body, 6)) { testrig_close(NULL); } } diff --git a/src/help.c b/src/help.c index 439c561..ad12408 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ int help_me(other_args* which) { else if (!strncmp("stat", which_one, 5)) { printhelp_stat(); return 0; } else if (!strncmp("daemon", which_one, 7)) { printhelp_daemon(); return 0; } else if (!strncmp("open", which_one, 5)) { printhelp_open(); return 0; } - else if (!strncmp("request", which_one, 7)) { printhelp_request(); return 0; } + else if (!strncmp("peek", which_one, 7)) { printhelp_peek(); return 0; } else if (!strncmp("close", which_one, 6)) { printhelp_close(); return 0; } else { printf("invalid target for \"help\"\n"); return 1; } } @@ -32,7 +32,7 @@ void print_usage(void) { "ident Identify connected controllers.\n" "stat Determine the status of connected controllers.\n" "open Open connection to a device.\n" - "request Request a CAN frame and print it out to stdout.\n" + "peek Request a CAN frame and print it out to stdout.\n" "close Close connection to device and release it.\n"); printf("\n"); } @@ -75,8 +75,8 @@ void printhelp_open(void) { "\n"); } -void printhelp_request(void) { - printf("testrig request\n"); +void printhelp_peek(void) { + printf("testrig peek\n"); print_hline(5); printf("Request a CAN frame and send it to stdout." "\n"); diff --git a/src/help.h b/src/help.h index 11eccaf..c794d97 100644 --- a/src/help.h +++ b/src/help.h @@ -11,5 +11,5 @@ void printhelp_ident(void); void printhelp_stat(void); void printhelp_daemon(void); void printhelp_open(void); -void printhelp_request(void); +void printhelp_peek(void); void printhelp_close(void); From e8df23f2c489507ed00cb90b952ebb6638c640a1 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Tue, 21 Apr 2026 08:42:15 -0500 Subject: [PATCH 02/34] Glob all srcs and headers --- .github/workflows/build-cmake.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-cmake.yml b/.github/workflows/build-cmake.yml index b5d5569..10a08a1 100644 --- a/.github/workflows/build-cmake.yml +++ b/.github/workflows/build-cmake.yml @@ -5,18 +5,16 @@ on: branches: ["main"] paths: - ".github/workflows/build-cmake.yml" - - "ipc/**/*.c" - - "ipc/**/*.h" - - "test/*.c" + - "**/*.c" + - "**/*.h" - "**/CMakeLists.txt" - "cmake/*.cmake" push: branches: ["main"] paths: - ".github/workflows/build-cmake.yml" - - "ipc/**/*.c" - - "ipc/**/*.h" - - "test/*.c" + - "**/*.c" + - "**/*.h" - "**/CMakeLists.txt" - "cmake/*.cmake" From a377c82502e3927f509d2e9bb0cd137fb4fbf56f Mon Sep 17 00:00:00 2001 From: JC Luna Date: Tue, 21 Apr 2026 10:20:57 -0500 Subject: [PATCH 03/34] Remote stoppage of the daemon --- src/args.c | 5 ++--- src/daemon.c | 34 +++++++++++++++++++++++++++------- src/help.c | 6 +++--- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/args.c b/src/args.c index ec78285..2f64631 100644 --- a/src/args.c +++ b/src/args.c @@ -34,8 +34,7 @@ int parse_flag(const char* flag, struct parsed_args* parsed) { const char* name = strstr(flag, "--") + 2; int ret = 0; - if (!strncmp("daemon", name, 7)) { parsed->action = ACTION_DAEMON; ret = 1; } - else if (!strncmp("detach", name, 7)) { parsed->mode = CLI_MODE_DETACHED; ret = 1; } + if (!strncmp("detach", name, 7)) { parsed->mode = CLI_MODE_DETACHED; ret = 1; } else if (!strncmp("verbose", name, 8)) { parsed->verbosity = 1; ret = 1; } else if (!strncmp("help", name, 5)) { parsed->action = ACTION_HELP; ret = 1; } @@ -49,7 +48,7 @@ int parse_act(const char* act, struct parsed_args* parsed) { else if (!strncmp("ident", act, 6)) { parsed->action = ACTION_IDENT; ret = 1; } else if (!strncmp("status", act, 7)) { parsed->action = ACTION_STAT; ret = 1; } else if (!strncmp("open", act, 5)) { parsed->action = ACTION_OPEN; ret = 1; } - else if (!strncmp("peek", act, 7)) { parsed->action = ACTION_REQUEST; ret = 1; } + else if (!strncmp("peek", act, 7)) { parsed->action = ACTION_REQUEST; ret = 1; } else if (!strncmp("close", act, 6)) { parsed->action = ACTION_CLOSE; ret = 1; } else if (!strncmp("help", act, 5)) { parsed->action = ACTION_HELP; ret = 1; } diff --git a/src/daemon.c b/src/daemon.c index bd0a16a..efcfd72 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -87,9 +87,9 @@ int seek_daemon(struct sockaddr_un* sockaddr) { return 1; } // int seek_daemon(struct sockaddir_un* sockaddr) -// }}} fold +// }}} Daemon Process and Socket Identification -int testrig_daemon([[maybe_unused]] other_args* others) { +int testrig_daemon(other_args* others) { int retstat = 0; struct sockaddr_un sockaddr = { .sun_family = AF_UNIX }; @@ -98,7 +98,26 @@ int testrig_daemon([[maybe_unused]] other_args* others) { socklen_t socksize = sizeof(sockaddr); int sought = seek_daemon(&sockaddr); - if (sought) { fprintf(stderr, "error: daemon already running\n"); return -1; } + + if (others != NULL && others->data != NULL + && !strncmp(others->data[0], "down", 6)) { + + vscl_byte_t body[8] = "DOWN"; + struct rig_message msg = { 0 }; + + vscl_set_message(&msg, HEAD_SYNC, body); + int conn = vscl_sock_connect(sock, &sockaddr); + if (conn == -1) { return -1; } + + int sent = vscl_sock_send(sock, &msg); + if (sent == -1) { return -1; } + + return 0; + } + else if (sought) { + fprintf(stderr, "error: daemon already running\n"); + return -1; + } if (!deploy_interrupt_cleanup(sock, &sockaddr)) { vscl_sock_close(sock, &sockaddr); @@ -137,10 +156,11 @@ int testrig_daemon([[maybe_unused]] other_args* others) { body[i - 4] = buf[i]; } - if (!strncmp("STATUS", body, 7)) { testrig_stat(NULL); } - else if (!strncmp("OPEN", body, 5)) { testrig_open(NULL); } - else if (!strncmp("REQUEST", body, 7)) { testrig_peek(NULL); } - else if (!strncmp("CLOSE", body, 6)) { testrig_close(NULL); } + if (!strncmp("STATUS", body, 7)) { testrig_stat(NULL); } + else if (!strncmp("OPEN", body, 5)) { testrig_open(NULL); } + else if (!strncmp("REQUEST", body, 7)) { testrig_peek(NULL); } + else if (!strncmp("CLOSE", body, 6)) { testrig_close(NULL); } + else if (!strncmp("DOWN", body, 5)) { DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_CLEANING; } } vscl_sock_close(sock, &sockaddr); diff --git a/src/help.c b/src/help.c index ad12408..f8233ee 100644 --- a/src/help.c +++ b/src/help.c @@ -16,7 +16,7 @@ int help_me(other_args* which) { else if (!strncmp("open", which_one, 5)) { printhelp_open(); return 0; } else if (!strncmp("peek", which_one, 7)) { printhelp_peek(); return 0; } else if (!strncmp("close", which_one, 6)) { printhelp_close(); return 0; } - else { printf("invalid target for \"help\"\n"); return 1; } + else { printf("invalid target for \"help\": \"%s\"\n", which_one); return 1; } } void print_usage(void) { @@ -24,11 +24,11 @@ void print_usage(void) { print_hline(5); printf("Options:\n" "--detach Detach the process from the shell.\n" - "--daemon Operate in daemon mode.\n" "--verbose Operate verbosely\n"); print_hline(5); printf("Actions:\n" "help Print out detailed help for a specific action.\n" + "daemon Operate on the daemon.\n" "ident Identify connected controllers.\n" "stat Determine the status of connected controllers.\n" "open Open connection to a device.\n" @@ -59,7 +59,7 @@ void printhelp_stat(void) { } void printhelp_daemon(void) { - printf("testrig daemon mode\n"); + printf("testrig daemon\n"); print_hline(5); printf("The process serves as a mediator between the controllers\n" "and other processes through an opened Unix socket,\n" From 7875d5b12a763003a651b2be1c840127cfd175e8 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Tue, 21 Apr 2026 16:25:32 -0500 Subject: [PATCH 04/34] Reorganize sources: ipc -> sock --- CMakeLists.txt | 1 + lib/ipc/ipc.c | 158 ---------------------------------------------- lib/ipc/ipc.h | 75 +--------------------- lib/ipc/message.c | 30 +++++++++ lib/ipc/message.h | 10 +++ lib/ipc/sock.c | 129 +++++++++++++++++++++++++++++++++++++ lib/ipc/sock.h | 71 +++++++++++++++++++++ 7 files changed, 244 insertions(+), 230 deletions(-) create mode 100644 lib/ipc/sock.c create mode 100644 lib/ipc/sock.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 610d778..531235c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ set(BIN_DIR "${CMAKE_SOURCE_DIR}/bin") set(IPC_SOURCES "${IPC_DIR}/ipc.c" + "${IPC_DIR}/sock.c" "${IPC_DIR}/message.c" "${IPC_DIR}/os.c") diff --git a/lib/ipc/ipc.c b/lib/ipc/ipc.c index 3a88628..3bc3949 100644 --- a/lib/ipc/ipc.c +++ b/lib/ipc/ipc.c @@ -1,159 +1 @@ -#include -#include -#include -#include - #include "ipc.h" -#include "os.h" - -#ifdef _WIN32 -// TODO: Evaluate if this is sufficient (it is honestly kind of smelly) -typedef int socklen_t; -#endif - -int vscl_sock_genpath(char* sockpath) { - int retstat; - int baselen; - //int dstart; - - retstat = vscl_get_sock_destination(sockpath); - baselen = strlen(sockpath); - - if (retstat != 0) { return retstat; } - - srand(time(NULL)); - for (int i = baselen; i < 32 + baselen - 1; i++) { - int start = (i % 2 == 0) ? 'a' : 'A'; - sockpath[i] = rand() % (25 + 1) + start; - } - - strncat(sockpath, ".rigsock", 9); - return 0; -} - -int vscl_sock_setup(struct sockaddr_un* sockaddr_mut) { - int fd; - int path_set; - char sockpath[108] = { 0 }; - char blank[108] = { 0 }; - -#ifdef _WIN32 - WSADATA wsa_data; - int wsa_result; - - wsa_result = WSAStartup(MAKEWORD(2, 2), &wsa_data); - if (wsa_result != 0) { perror("failed WSAStartup"); return -1; } -#endif // _WIN32 - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == INVALID_SOCKET) { perror("failed to create socket"); return -1; } - - path_set = (strncmp( - sockaddr_mut->sun_path, blank, - strnlen(sockaddr_mut->sun_path, 108)) == 0) ? -1 : 1; - - if (path_set == -1) { - vscl_sock_genpath(sockpath); - long long int sockpathlen = strnlen(sockpath, 108); - strncpy(sockaddr_mut->sun_path, sockpath, sockpathlen + 1); - } - - sockaddr_mut->sun_family = AF_UNIX; - return fd; -} - -int vscl_sock_bind(const int fd, const struct sockaddr_un* sockaddr) { - int bindstat; - socklen_t socklen; - - socklen = sizeof(*sockaddr); - bindstat = bind(fd, (struct sockaddr*)sockaddr, socklen); - if (bindstat == -1) { perror("failed to bind socket"); } - - return bindstat; -} - -int vscl_sock_listen(const int fd, int max_backlog) { - int listenstat; - - listenstat = listen(fd, max_backlog); - if (listenstat == -1) { perror("failed to set socket to listen"); } - - return listenstat; -} - -int vscl_sock_connect(const int fd, const struct sockaddr_un* sockaddr) { - int connstat; - socklen_t socklen; - - socklen = sizeof(*sockaddr); - connstat = connect(fd, (struct sockaddr*)sockaddr, socklen); - if (connstat == -1) { perror("failed to connect to socket"); } - - return connstat; -} - -int vscl_sock_close(const int fd, struct sockaddr_un* sockaddr) { - int closestat; - -#ifdef _WIN32 - closestat = closesocket(fd); -#else - closestat = close(fd); -#endif - remove(sockaddr->sun_path); - - return closestat; -} - -int vscl_sock_send(const int fd, struct rig_message* msg) { - int nbytes; - vscl_byte_t buf[12] = { 0 }; - - for (int i = 0; i < 4; i++) { - buf[i] = msg->head[i]; - } - - for (int i = 0; i < 8; i++) { - buf[i + 4] = msg->data[i]; - } - -#ifdef _WIN32 - nbytes = send(fd, buf, 12, MSG_DONTROUTE); -#else - nbytes = write(fd, buf, 12); -#endif - if (nbytes == -1) { perror("Clientside socket send error"); } - - return nbytes; -} - -int vscl_ident_header_part(vscl_byte_t in[4], int idx) { - if (in[idx] == HEAD_STAY[idx]) { - return HEADER_IS_STAY; - } - else if (in[idx] == HEAD_DC[idx]) { - return HEADER_IS_DC; - } - else if (in[idx] == HEAD_SYNC[idx]) { - return HEADER_IS_SYNC; - } - else { - return -1; - } -} - -int vscl_ident_full_header(vscl_byte_t in[4]) { - int identity = -1; - - for (int i = 0; i < 4; i++) { - if (i == 0) { - identity = vscl_ident_header_part(in, 0); - } - else { - identity &= vscl_ident_header_part(in, i); - } - } - - return identity; -} diff --git a/lib/ipc/ipc.h b/lib/ipc/ipc.h index 1277399..0fe8864 100644 --- a/lib/ipc/ipc.h +++ b/lib/ipc/ipc.h @@ -1,82 +1,13 @@ #pragma once -// Headers #ifdef __cplusplus extern "C" { #endif -#ifdef _WIN32 -#include -#include -#else -#include -#include -#include -#include -#endif // _WIN32 -#include -#include - -#include "ipc/os.h" #include "ipc/message.h" -#include "libtestrig_api.h" - -/* - * @brief Generate a path to a socket file. - * - * This is in a temporary path with the .rigsock extension. - */ -TESTRIG_API int vscl_sock_genpath(char* sockpath); - -/* - * @brief Create a Unix socket to a random file. - * - * Returns a nonzero int representing the file descriptor, otherwise -1. - */ -TESTRIG_API int vscl_sock_setup(struct sockaddr_un* sockaddr_mut); - -/* - * @brief Bind the Unix socket, using the path specified in the passed sockaddr_un struct. - * - * Returns 0 on success, -1 on failure. - */ -TESTRIG_API int vscl_sock_bind(const int fd, const struct sockaddr_un* sockaddr); - -/* - * @brief Set the Unix socket to listen and permit connection attempts. - * - * Returns 0 on success, -1 on failure. - */ -TESTRIG_API int vscl_sock_listen(const int fd, int max_backlog); - -/* - * @brief Connect the Unix Socket, using the path specified in the passed sockaddr_un struct. - * - * Returns 0 on success, -1 on failure. - */ -TESTRIG_API int vscl_sock_connect(const int fd, const struct sockaddr_un* sockaddr); - -/* - * @brief Close the socket and clean up. - */ -TESTRIG_API int vscl_sock_close(const int fd, struct sockaddr_un* sockaddr); - -/* - * @brief Send a message over the socket without waiting for a response. - * TODO: make version that waits - */ -TESTRIG_API int vscl_sock_send(const int fd, struct rig_message* msg); - -/* - * @brief Identify the header byte. - */ -TESTRIG_API int vscl_ident_header_part(vscl_byte_t in[4], int idx); - -/* - * @brief Identify the four bytes in the header. - */ -TESTRIG_API int vscl_ident_full_header(vscl_byte_t in[4]); +#include "ipc/os.h" +#include "ipc/sock.h" #ifdef __cplusplus } // extern "C" -#endif \ No newline at end of file +#endif diff --git a/lib/ipc/message.c b/lib/ipc/message.c index 976e26e..af395c5 100644 --- a/lib/ipc/message.c +++ b/lib/ipc/message.c @@ -14,3 +14,33 @@ int vscl_set_message(struct rig_message* msg, const vscl_byte_t* head, const vsc memcpy(msg->data, data, 8); return 0; } + +int vscl_ident_header_part(vscl_byte_t in[4], int idx) { + if (in[idx] == HEAD_STAY[idx]) { + return HEADER_IS_STAY; + } + else if (in[idx] == HEAD_DC[idx]) { + return HEADER_IS_DC; + } + else if (in[idx] == HEAD_SYNC[idx]) { + return HEADER_IS_SYNC; + } + else { + return -1; + } +} + +int vscl_ident_full_header(vscl_byte_t in[4]) { + int identity = -1; + + for (int i = 0; i < 4; i++) { + if (i == 0) { + identity = vscl_ident_header_part(in, 0); + } + else { + identity &= vscl_ident_header_part(in, i); + } + } + + return identity; +} diff --git a/lib/ipc/message.h b/lib/ipc/message.h index 14d6d25..ecbf6e4 100644 --- a/lib/ipc/message.h +++ b/lib/ipc/message.h @@ -48,6 +48,16 @@ TESTRIG_API extern const vscl_byte_t MESSAGE_BLANK[8]; // Convenience function that encapsulates copying to the header and data fields. TESTRIG_API int vscl_set_message(struct rig_message* msg, const vscl_byte_t* head, const vscl_byte_t* data); +/* + * @brief Identify the header byte. + */ +TESTRIG_API int vscl_ident_header_part(vscl_byte_t in[4], int idx); + +/* + * @brief Identify the four bytes in the header. + */ +TESTRIG_API int vscl_ident_full_header(vscl_byte_t in[4]); + /* * The type of header. */ diff --git a/lib/ipc/sock.c b/lib/ipc/sock.c new file mode 100644 index 0000000..f776489 --- /dev/null +++ b/lib/ipc/sock.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include + +#include "sock.h" +#include "os.h" + +#ifdef _WIN32 +// TODO: Evaluate if this is sufficient (it is honestly kind of smelly) +typedef int socklen_t; +#endif + +int vscl_sock_genpath(char* sockpath) { + int retstat; + int baselen; + //int dstart; + + retstat = vscl_get_sock_destination(sockpath); + baselen = strlen(sockpath); + + if (retstat != 0) { return retstat; } + + srand(time(NULL)); + for (int i = baselen; i < 32 + baselen - 1; i++) { + int start = (i % 2 == 0) ? 'a' : 'A'; + sockpath[i] = rand() % (25 + 1) + start; + } + + strncat(sockpath, ".rigsock", 9); + return 0; +} + +int vscl_sock_setup(struct sockaddr_un* sockaddr_mut) { + int fd; + int path_set; + char sockpath[108] = { 0 }; + char blank[108] = { 0 }; + +#ifdef _WIN32 + WSADATA wsa_data; + int wsa_result; + + wsa_result = WSAStartup(MAKEWORD(2, 2), &wsa_data); + if (wsa_result != 0) { perror("failed WSAStartup"); return -1; } +#endif // _WIN32 + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == INVALID_SOCKET) { perror("failed to create socket"); return -1; } + + path_set = (strncmp( + sockaddr_mut->sun_path, blank, + strnlen(sockaddr_mut->sun_path, 108)) == 0) ? -1 : 1; + + if (path_set == -1) { + vscl_sock_genpath(sockpath); + long long int sockpathlen = strnlen(sockpath, 108); + strncpy(sockaddr_mut->sun_path, sockpath, sockpathlen + 1); + } + + sockaddr_mut->sun_family = AF_UNIX; + return fd; +} + +int vscl_sock_bind(const int fd, const struct sockaddr_un* sockaddr) { + int bindstat; + socklen_t socklen; + + socklen = sizeof(*sockaddr); + bindstat = bind(fd, (struct sockaddr*)sockaddr, socklen); + if (bindstat == -1) { perror("failed to bind socket"); } + + return bindstat; +} + +int vscl_sock_listen(const int fd, int max_backlog) { + int listenstat; + + listenstat = listen(fd, max_backlog); + if (listenstat == -1) { perror("failed to set socket to listen"); } + + return listenstat; +} + +int vscl_sock_connect(const int fd, const struct sockaddr_un* sockaddr) { + int connstat; + socklen_t socklen; + + socklen = sizeof(*sockaddr); + connstat = connect(fd, (struct sockaddr*)sockaddr, socklen); + if (connstat == -1) { perror("failed to connect to socket"); } + + return connstat; +} + +int vscl_sock_close(const int fd, struct sockaddr_un* sockaddr) { + int closestat; + +#ifdef _WIN32 + closestat = closesocket(fd); +#else + closestat = close(fd); +#endif + remove(sockaddr->sun_path); + + return closestat; +} + +int vscl_sock_send(const int fd, struct rig_message* msg) { + int nbytes; + vscl_byte_t buf[12] = { 0 }; + + for (int i = 0; i < 4; i++) { + buf[i] = msg->head[i]; + } + + for (int i = 0; i < 8; i++) { + buf[i + 4] = msg->data[i]; + } + +#ifdef _WIN32 + nbytes = send(fd, buf, 12, MSG_DONTROUTE); +#else + nbytes = write(fd, buf, 12); +#endif + if (nbytes == -1) { perror("Clientside socket send error"); } + + return nbytes; +} diff --git a/lib/ipc/sock.h b/lib/ipc/sock.h new file mode 100644 index 0000000..ad3af42 --- /dev/null +++ b/lib/ipc/sock.h @@ -0,0 +1,71 @@ +#pragma once + +// Headers +#ifdef __cplusplus +extern "C" { +#endif +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#endif // _WIN32 + +#include +#include + +#include "ipc/message.h" +#include "libtestrig_api.h" + +/* + * @brief Generate a path to a socket file. + * + * This is in a temporary path with the .rigsock extension. + */ +TESTRIG_API int vscl_sock_genpath(char* sockpath); + +/* + * @brief Create a Unix socket to a random file. + * + * Returns a nonzero int representing the file descriptor, otherwise -1. + */ +TESTRIG_API int vscl_sock_setup(struct sockaddr_un* sockaddr_mut); + +/* + * @brief Bind the Unix socket, using the path specified in the passed sockaddr_un struct. + * + * Returns 0 on success, -1 on failure. + */ +TESTRIG_API int vscl_sock_bind(const int fd, const struct sockaddr_un* sockaddr); + +/* + * @brief Set the Unix socket to listen and permit connection attempts. + * + * Returns 0 on success, -1 on failure. + */ +TESTRIG_API int vscl_sock_listen(const int fd, int max_backlog); + +/* + * @brief Connect the Unix Socket, using the path specified in the passed sockaddr_un struct. + * + * Returns 0 on success, -1 on failure. + */ +TESTRIG_API int vscl_sock_connect(const int fd, const struct sockaddr_un* sockaddr); + +/* + * @brief Close the socket and clean up. + */ +TESTRIG_API int vscl_sock_close(const int fd, struct sockaddr_un* sockaddr); + +/* + * @brief Send a message over the socket without waiting for a response. + * TODO: make version that waits + */ +TESTRIG_API int vscl_sock_send(const int fd, struct rig_message* msg); + +#ifdef __cplusplus +} // extern "C" +#endif From bdd759b380747e040d17f093d810b0ddf7135653 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Tue, 21 Apr 2026 19:32:33 -0500 Subject: [PATCH 05/34] maybe ifdefing in a struct is evil --- CMakeLists.txt | 1 + lib/ipc/pipe.c | 35 +++++++++++++++++++++++++++++++++++ lib/ipc/pipe.h | 30 ++++++++++++++++++++++++++++++ lib/libtestrig_api.h | 7 ++++++- 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 lib/ipc/pipe.c create mode 100644 lib/ipc/pipe.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 531235c..157c601 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ set(BIN_DIR "${CMAKE_SOURCE_DIR}/bin") set(IPC_SOURCES "${IPC_DIR}/ipc.c" "${IPC_DIR}/sock.c" + "${IPC_DIR}/pipe.c" "${IPC_DIR}/message.c" "${IPC_DIR}/os.c") diff --git a/lib/ipc/pipe.c b/lib/ipc/pipe.c new file mode 100644 index 0000000..19d4041 --- /dev/null +++ b/lib/ipc/pipe.c @@ -0,0 +1,35 @@ +#include +#include "ipc/pipe.h" + +vscl_pipe_t vscl_create_pipes() { + + vscl_pipe_t piper = { 0 }; + +#if _WIN32 + SECURITY_ATTRIBUTES sattrs = { 0 }; + sattrs.nLength = sizeof(SECURITY_ATTRIBUTES); + sattrs.bInheritHandle = TRUE; + sattrs.lpSecurityDescriptor = NULL; + + if (!CreatePipe(&piper.child_read, &piper.child_write, &sattrs, 0)) + vscl_winprint_error(L"While creating child read pipe"); + + if (!SetHandleInformation(piper.child_read, HANDLE_FLAG_INHERIT, 0)) + vscl_winprint_error(L"While preventing child from taking parent pipe attributes"); + +#else + int pipestat = pipe(piper.linux_fds); + if (pipestat == -1) { perror("While creating pipes"); } + +#endif + + return piper; +} + +int vscl_read_pipe(vscl_pipe_t* pipe, vscl_byte_t* buf) { + return 0; +} + +int vscl_write_pipe(vscl_pipe_t* pipe, vscl_byte_t* buf) { + return 0; +} diff --git a/lib/ipc/pipe.h b/lib/ipc/pipe.h new file mode 100644 index 0000000..ddf201d --- /dev/null +++ b/lib/ipc/pipe.h @@ -0,0 +1,30 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "libtestrig_api.h" + +typedef struct { +#ifdef _WIN32 + HANDLE child_write; + HANDLE child_read; +#else + int linux_fds[2]; +#endif +} vscl_pipe_t; + +TESTRIG_API vscl_pipe_t vscl_create_pipes(void); +TESTRIG_API int vscl_read_pipe(vscl_pipe_t* pipe, vscl_byte_t* buf); +TESTRIG_API int vscl_write_pipe(vscl_pipe_t* pipe, vscl_byte_t* buf); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/lib/libtestrig_api.h b/lib/libtestrig_api.h index b6445aa..23aa96d 100644 --- a/lib/libtestrig_api.h +++ b/lib/libtestrig_api.h @@ -12,4 +12,9 @@ #endif // _WIN32 #endif // TESTRIG_API -typedef char vscl_byte_t; \ No newline at end of file +typedef char vscl_byte_t; + +enum VSCL_PLATFORM { + VSCL_PLATFORM_WINDOWS, + VSCL_PLATFORM_LINUX, +}; From a60b1bd07641a849c9c7f879d480b1eb9f6be20b Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 09:38:45 -0500 Subject: [PATCH 06/34] Enforce header order --- CMakeLists.txt | 2 +- lib/ipc/ipc.h | 1 + lib/ipc/os.h | 8 ++++---- lib/ipc/pipe.c | 5 +++-- lib/ipc/pipe.h | 2 +- lib/ipc/sock.h | 7 +++---- lib/ipc/win_headers.h | 5 +++++ stupid.txt | 4 ---- 8 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 lib/ipc/win_headers.h delete mode 100644 stupid.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 157c601..b6c06cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ set(BIN_DIR "${CMAKE_SOURCE_DIR}/bin") set(IPC_SOURCES "${IPC_DIR}/ipc.c" - "${IPC_DIR}/sock.c" "${IPC_DIR}/pipe.c" + "${IPC_DIR}/sock.c" "${IPC_DIR}/message.c" "${IPC_DIR}/os.c") diff --git a/lib/ipc/ipc.h b/lib/ipc/ipc.h index 0fe8864..9167569 100644 --- a/lib/ipc/ipc.h +++ b/lib/ipc/ipc.h @@ -7,6 +7,7 @@ extern "C" { #include "ipc/message.h" #include "ipc/os.h" #include "ipc/sock.h" +#include "ipc/pipe.h" #ifdef __cplusplus } // extern "C" diff --git a/lib/ipc/os.h b/lib/ipc/os.h index f0f294a..555192b 100644 --- a/lib/ipc/os.h +++ b/lib/ipc/os.h @@ -1,13 +1,13 @@ #pragma once -#ifdef _WIN32 -#include -#endif - #ifdef __cplusplus extern "C" { #endif // __cplusplus +#ifdef _WIN32 +#include "win_headers.h" +#endif + #include "libtestrig_api.h" #ifndef _WIN32 diff --git a/lib/ipc/pipe.c b/lib/ipc/pipe.c index 19d4041..fecd5f3 100644 --- a/lib/ipc/pipe.c +++ b/lib/ipc/pipe.c @@ -1,5 +1,6 @@ #include #include "ipc/pipe.h" +#include "ipc/os.h" vscl_pipe_t vscl_create_pipes() { @@ -12,10 +13,10 @@ vscl_pipe_t vscl_create_pipes() { sattrs.lpSecurityDescriptor = NULL; if (!CreatePipe(&piper.child_read, &piper.child_write, &sattrs, 0)) - vscl_winprint_error(L"While creating child read pipe"); + vscl_winprint_error("While creating child read pipe"); if (!SetHandleInformation(piper.child_read, HANDLE_FLAG_INHERIT, 0)) - vscl_winprint_error(L"While preventing child from taking parent pipe attributes"); + vscl_winprint_error("While preventing child from taking parent pipe attributes"); #else int pipestat = pipe(piper.linux_fds); diff --git a/lib/ipc/pipe.h b/lib/ipc/pipe.h index ddf201d..92d0236 100644 --- a/lib/ipc/pipe.h +++ b/lib/ipc/pipe.h @@ -5,7 +5,7 @@ extern "C" { #endif #ifdef _WIN32 -#include +#include "ipc/win_headers.h" #else #include #endif diff --git a/lib/ipc/sock.h b/lib/ipc/sock.h index ad3af42..25d2128 100644 --- a/lib/ipc/sock.h +++ b/lib/ipc/sock.h @@ -4,14 +4,13 @@ #ifdef __cplusplus extern "C" { #endif -#ifdef _WIN32 -#include -#include -#else +#ifndef _WIN32 #include #include #include #include +#else +#include "ipc/win_headers.h" #endif // _WIN32 #include diff --git a/lib/ipc/win_headers.h b/lib/ipc/win_headers.h new file mode 100644 index 0000000..070e898 --- /dev/null +++ b/lib/ipc/win_headers.h @@ -0,0 +1,5 @@ +#ifdef _WIN32 +#include +#include +#include +#endif \ No newline at end of file diff --git a/stupid.txt b/stupid.txt deleted file mode 100644 index 2b68643..0000000 --- a/stupid.txt +++ /dev/null @@ -1,4 +0,0 @@ -testrigd not running; creating new testrig process at 47324 -Waiting for connection... -Accepted -Stopping... From 1e1899158e80933f46b8f824c8029654472ec6bc Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 09:27:36 -0500 Subject: [PATCH 07/34] Small trivial sockname unit test --- CMakeLists.txt | 1 + test/CMakeLists.txt | 3 +++ test/ipc/CMakeLists.txt | 8 ++++++++ test/ipc/sock_naming.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 test/CMakeLists.txt create mode 100644 test/ipc/CMakeLists.txt create mode 100644 test/ipc/sock_naming.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b6c06cc..7fc9f8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,3 +63,4 @@ if (WIN32) endif() add_subdirectory("${CMAKE_SOURCE_DIR}/src") +add_subdirectory("${CMAKE_SOURCE_DIR}/test") \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..d661971 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,3 @@ +enable_testing() + +add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ipc") \ No newline at end of file diff --git a/test/ipc/CMakeLists.txt b/test/ipc/CMakeLists.txt new file mode 100644 index 0000000..47739ec --- /dev/null +++ b/test/ipc/CMakeLists.txt @@ -0,0 +1,8 @@ +function(make_ipc_test OUT_TGT_NAME IN_SOURCES) + add_executable(${OUT_TGT_NAME} ${IN_SOURCES}) + target_link_libraries(${OUT_TGT_NAME} PRIVATE libtestrig) + target_copy_dll(${OUT_TGT_NAME}) + add_test(NAME "${OUT_TGT_NAME}_test" COMMAND $) +endfunction(make_ipc_test OUT_TGT_NAME IN_SOURCES) + +make_ipc_test(sock_test_suite "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") \ No newline at end of file diff --git a/test/ipc/sock_naming.c b/test/ipc/sock_naming.c new file mode 100644 index 0000000..5601685 --- /dev/null +++ b/test/ipc/sock_naming.c @@ -0,0 +1,34 @@ +#include +#include +#include + +#include "ipc/sock.h" +#include "ipc/os.h" + +int main(int argc, char** argv) { + printf("Begin socket test suite.\n"); + int retstat = 0; + + char sockdest[108] = { 0 }; + retstat = vscl_get_sock_destination(sockdest); + if (retstat != 0) { fprintf(stderr, "Failed to find socket path: sockpath became %s\n", sockdest); return retstat; } + + printf("Sockets will go to %s\n", sockdest); + memset(sockdest, 0, 1); + retstat = vscl_sock_genpath(sockdest); + if (retstat != 0) { fprintf(stderr, "Could not generate a proper path for the socket.\n"); return retstat; } + + char new_sockdest[108] = { 0 }; + retstat = vscl_sock_genpath(new_sockdest); + if (retstat != 0) { fprintf(stderr, "Could not generate a proper path for the fresh socket.\n"); return retstat; } + + printf("The socket path was randomly: %s\n", sockdest); + printf("The fresh socket path was randomly: %s\n", new_sockdest); + + // Ensure no early truncation + assert(strstr(sockdest, ".rigsock") != NULL); + assert(strstr(new_sockdest, ".rigsock") != NULL); + printf("The socket path was not truncated.\n"); + + return 0; +} \ No newline at end of file From 6e85319c9944418e0e9ce9e162acbf7e78d056e9 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 10:06:09 -0500 Subject: [PATCH 08/34] CTest on CI --- .github/workflows/build-cmake.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-cmake.yml b/.github/workflows/build-cmake.yml index 10a08a1..25c9a91 100644 --- a/.github/workflows/build-cmake.yml +++ b/.github/workflows/build-cmake.yml @@ -36,6 +36,9 @@ jobs: - name: Build run: | cmake --build build + - name: Test + run: | + ctest --verbose --output-on-failure --test-dir ${{ github.workspace }}/build/test windows-build-cmake: name: Windows @@ -55,3 +58,6 @@ jobs: - name: Build run: | cmake --build build + - name: Test + run: | + ctest --verbose --output-on-failure --test-dir ${{ github.workspace }}/build/test From 52bdc6036ab6966490746db1510f1d1bac879801 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 10:14:50 -0500 Subject: [PATCH 09/34] Emit warnings this way --- CMakeLists.txt | 9 ++------- cmake/target_compile_warn_all.cmake | 7 +++++++ src/CMakeLists.txt | 1 + test/ipc/CMakeLists.txt | 4 +++- test/ipc/sock_communicating.c | 3 +++ test/ipc/sock_naming.c | 4 ++-- 6 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 cmake/target_compile_warn_all.cmake create mode 100644 test/ipc/sock_communicating.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fc9f8b..f3e2321 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ project(libtestrig include(target_copy_dll) include(target_output_to_bin) +include(target_compile_warn_all) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib") @@ -29,13 +30,6 @@ set(EPOS_SOURCES set(LIBTESTRIG_SOURCES ${IPC_SOURCES} ${EPOS_SOURCES}) -if (MSVC) - add_compile_options("/W4") -else() - add_compile_options("-Wall") -endif() - - if (WIN32) add_library(EposCmd SHARED IMPORTED) set_target_properties(EposCmd PROPERTIES @@ -56,6 +50,7 @@ add_library(libtestrig SHARED ${LIBTESTRIG_SOURCES}) target_compile_definitions(libtestrig PRIVATE COMPILING_TESTRIG_DLL) target_include_directories(libtestrig PUBLIC ${LIB_DIR}) target_link_libraries(libtestrig PUBLIC EposCmd) +target_compile_warn_all(libtestrig) target_output_to_bin(libtestrig) if (WIN32) diff --git a/cmake/target_compile_warn_all.cmake b/cmake/target_compile_warn_all.cmake new file mode 100644 index 0000000..99a7d4c --- /dev/null +++ b/cmake/target_compile_warn_all.cmake @@ -0,0 +1,7 @@ +function(target_compile_warn_all IN_TARGET_NAME) + if (MSVC) + target_compile_options(${IN_TARGET_NAME} PRIVATE "/W4") + else() + target_compile_options(${IN_TARGET_NAME} PRIVATE "-Wall") + endif() +endfunction(target_compile_warn_all IN_TARGET_NAME) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 14dd2f0..d78669a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,4 +8,5 @@ set(TESTRIG_SOURCES add_executable(testrig ${TESTRIG_SOURCES}) target_link_libraries(testrig PRIVATE libtestrig) target_include_directories(testrig PRIVATE ${LIB_DIR}) +target_compile_warn_all(testrig) target_output_to_bin(testrig) \ No newline at end of file diff --git a/test/ipc/CMakeLists.txt b/test/ipc/CMakeLists.txt index 47739ec..88015ec 100644 --- a/test/ipc/CMakeLists.txt +++ b/test/ipc/CMakeLists.txt @@ -2,7 +2,9 @@ function(make_ipc_test OUT_TGT_NAME IN_SOURCES) add_executable(${OUT_TGT_NAME} ${IN_SOURCES}) target_link_libraries(${OUT_TGT_NAME} PRIVATE libtestrig) target_copy_dll(${OUT_TGT_NAME}) + target_compile_warn_all(${OUT_TGT_NAME}) add_test(NAME "${OUT_TGT_NAME}_test" COMMAND $) endfunction(make_ipc_test OUT_TGT_NAME IN_SOURCES) -make_ipc_test(sock_test_suite "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") \ No newline at end of file +make_ipc_test(sock_naming "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") +make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c") \ No newline at end of file diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c new file mode 100644 index 0000000..9eab473 --- /dev/null +++ b/test/ipc/sock_communicating.c @@ -0,0 +1,3 @@ +int main(int argc, char** argv) { + return 0; +} \ No newline at end of file diff --git a/test/ipc/sock_naming.c b/test/ipc/sock_naming.c index 5601685..903d999 100644 --- a/test/ipc/sock_naming.c +++ b/test/ipc/sock_naming.c @@ -5,8 +5,8 @@ #include "ipc/sock.h" #include "ipc/os.h" -int main(int argc, char** argv) { - printf("Begin socket test suite.\n"); +int main(void) { + printf("Begin socket naming tests.\n"); int retstat = 0; char sockdest[108] = { 0 }; From 7948f2edbff4a53018395c1d93a55df7fd06ee95 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 10:27:59 -0500 Subject: [PATCH 10/34] Test the proc spawner --- lib/libtestrig_api.h | 2 +- test/ipc/CMakeLists.txt | 12 ++++++++++-- test/ipc/sock_communicating.c | 13 +++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/lib/libtestrig_api.h b/lib/libtestrig_api.h index 23aa96d..812e0e2 100644 --- a/lib/libtestrig_api.h +++ b/lib/libtestrig_api.h @@ -17,4 +17,4 @@ typedef char vscl_byte_t; enum VSCL_PLATFORM { VSCL_PLATFORM_WINDOWS, VSCL_PLATFORM_LINUX, -}; +}; \ No newline at end of file diff --git a/test/ipc/CMakeLists.txt b/test/ipc/CMakeLists.txt index 88015ec..759a7a7 100644 --- a/test/ipc/CMakeLists.txt +++ b/test/ipc/CMakeLists.txt @@ -1,10 +1,18 @@ function(make_ipc_test OUT_TGT_NAME IN_SOURCES) + + if (${ARGC} GREATER 2) + set(_other_args ${ARGV2}) + else() + set(_other_args) + endif() + add_executable(${OUT_TGT_NAME} ${IN_SOURCES}) target_link_libraries(${OUT_TGT_NAME} PRIVATE libtestrig) target_copy_dll(${OUT_TGT_NAME}) target_compile_warn_all(${OUT_TGT_NAME}) - add_test(NAME "${OUT_TGT_NAME}_test" COMMAND $) + add_test(NAME "${OUT_TGT_NAME}_test" COMMAND $ ${_other_args}) + endfunction(make_ipc_test OUT_TGT_NAME IN_SOURCES) make_ipc_test(sock_naming "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") -make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c") \ No newline at end of file +make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "serve") \ No newline at end of file diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c index 9eab473..c1b5af2 100644 --- a/test/ipc/sock_communicating.c +++ b/test/ipc/sock_communicating.c @@ -1,3 +1,16 @@ +#include "ipc/sock.h" +#include "ipc/os.h" +#include + int main(int argc, char** argv) { + printf("This was invoked with the following command line:\n"); + printf("\t%s %s\n", argv[0], argv[1]); + + if (strncmp(argv[1], "serve", 6) == 0) { + int retstat = vscl_make_new_proc(argv[0], "child"); + if (retstat == -1) { fprintf(stderr, "Failure to launch\n"); return retstat; } + else { printf("New process was spawned with PID %i\n", retstat); } + } + return 0; } \ No newline at end of file From 28db905dec84e5bf93b49b6fc66f0c47bf787412 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 12:34:32 -0500 Subject: [PATCH 11/34] Simple socket full run test --- test/ipc/CMakeLists.txt | 2 +- test/ipc/sock_communicating.c | 75 ++++++++++++++++++++++++++++++++--- test/ipc/sock_naming.c | 4 +- 3 files changed, 72 insertions(+), 9 deletions(-) diff --git a/test/ipc/CMakeLists.txt b/test/ipc/CMakeLists.txt index 759a7a7..8a7e82b 100644 --- a/test/ipc/CMakeLists.txt +++ b/test/ipc/CMakeLists.txt @@ -15,4 +15,4 @@ function(make_ipc_test OUT_TGT_NAME IN_SOURCES) endfunction(make_ipc_test OUT_TGT_NAME IN_SOURCES) make_ipc_test(sock_naming "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") -make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "serve") \ No newline at end of file +make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "parent") diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c index c1b5af2..c737eb6 100644 --- a/test/ipc/sock_communicating.c +++ b/test/ipc/sock_communicating.c @@ -2,15 +2,78 @@ #include "ipc/os.h" #include +static const char* TESTER_SOCK_NAME = "TEST_SOCK.rigsock"; // NOLINT + int main(int argc, char** argv) { printf("This was invoked with the following command line:\n"); printf("\t%s %s\n", argv[0], argv[1]); + + char sockpath[108] = { 0 }; + int retstat = vscl_get_sock_destination(sockpath); + if (retstat != 0) { + fprintf(stderr, + "While preparing the sockets, socket destination grabbing failed.\n"); + return retstat; + } + + strncat(sockpath, TESTER_SOCK_NAME, 19); + struct sockaddr_un sockaddr = { .sun_family = AF_UNIX, }; + strncpy(sockaddr.sun_path, sockpath, 108); + + if (strncmp(argv[1], "parent", 6) == 0) { + int parented = vscl_sock_setup(&sockaddr); + if (parented == INVALID_SOCKET) { fprintf(stderr, "Parent sock maker fail\n"); return -1; } + + int parentstat = vscl_sock_bind(parented, &sockaddr); + if (parentstat == -1) { fprintf(stderr, "Sock binder fail\n"); return parentstat; } + + parentstat = vscl_sock_listen(parented, 1); + if (parentstat == -1) { + int closestat = vscl_sock_close(parented, &sockaddr); + return (!closestat) ? closestat : parentstat; + } + + // Race condition? + parentstat = vscl_make_new_proc(argv[0], "child"); + if (parentstat == -1) { fprintf(stderr, "Failure to launch\n"); return parentstat; } + else { printf("New process was spawned with PID %i\n", parentstat); } - if (strncmp(argv[1], "serve", 6) == 0) { - int retstat = vscl_make_new_proc(argv[0], "child"); - if (retstat == -1) { fprintf(stderr, "Failure to launch\n"); return retstat; } - else { printf("New process was spawned with PID %i\n", retstat); } + int exitplz = 0; + socklen_t socklen = (socklen_t)sizeof(sockaddr); + while (!exitplz) { + int acceptor = accept(parented, (struct sockaddr*)&sockaddr, &socklen); + if (acceptor == -1) { fprintf(stderr, "Accept epic fail\n"); continue; } + + vscl_byte_t buf[12] = { 0 }; + +#ifdef _WIN32 + int recvd = recv(accepted, buf, 12, MSG_PEEK); +#else + int recvd = read(acceptor, buf, 12); +#endif + if (recvd != 12) { + fprintf(stderr, "Failure to read full msg: %i out of 12\n", recvd); + vscl_sock_close(parented, &sockaddr); + return recvd; + } + + printf("Success: The message I got was %s\n", buf); + assert(strncmp(buf, "HOWDY WORLD", 12) == 0); + } + + return vscl_sock_close(parented, &sockaddr); } + else if (strncmp(argv[1], "child", 6) == 0) { + struct sockaddr_un childsock = { 0 }; + int childed = vscl_sock_setup(&childsock); + if (childed == INVALID_SOCKET) { fprintf(stderr, "Child sock maker fail\n"); return -1; } + + int connection = vscl_sock_connect(childed, &sockaddr); + if (connection == -1) { fprintf(stderr, "Child connection fail\n"); return connection; } + + struct rig_message msg = { {'H', 'O', 'W', 'D'}, {'Y', ' ', 'W', 'O', 'R', 'L', 'D', 0} }; + vscl_sock_send(connection, &msg); - return 0; -} \ No newline at end of file + return vscl_sock_close(childed, &childsock); + } +} diff --git a/test/ipc/sock_naming.c b/test/ipc/sock_naming.c index 903d999..c712a1b 100644 --- a/test/ipc/sock_naming.c +++ b/test/ipc/sock_naming.c @@ -28,7 +28,7 @@ int main(void) { // Ensure no early truncation assert(strstr(sockdest, ".rigsock") != NULL); assert(strstr(new_sockdest, ".rigsock") != NULL); - printf("The socket path was not truncated.\n"); + printf("Success: The socket path was not truncated.\n"); return 0; -} \ No newline at end of file +} From ca01f9739467ad0732ed0bfd8c51d3a436e05df5 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 12:39:39 -0500 Subject: [PATCH 12/34] Windows define a socklen_t --- lib/ipc/os.h | 3 ++- lib/ipc/sock.h | 1 + test/ipc/sock_communicating.c | 11 ++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/ipc/os.h b/lib/ipc/os.h index 555192b..5c3c670 100644 --- a/lib/ipc/os.h +++ b/lib/ipc/os.h @@ -10,7 +10,8 @@ extern "C" { #include "libtestrig_api.h" -#ifndef _WIN32 +#ifdef _WIN32 +#else #define INVALID_SOCKET -1 #endif diff --git a/lib/ipc/sock.h b/lib/ipc/sock.h index 25d2128..5955816 100644 --- a/lib/ipc/sock.h +++ b/lib/ipc/sock.h @@ -11,6 +11,7 @@ extern "C" { #include #else #include "ipc/win_headers.h" +#define socklen_t socklen #endif // _WIN32 #include diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c index c737eb6..9def558 100644 --- a/test/ipc/sock_communicating.c +++ b/test/ipc/sock_communicating.c @@ -59,6 +59,8 @@ int main(int argc, char** argv) { printf("Success: The message I got was %s\n", buf); assert(strncmp(buf, "HOWDY WORLD", 12) == 0); + + exitplz = 1; } return vscl_sock_close(parented, &sockaddr); @@ -72,7 +74,14 @@ int main(int argc, char** argv) { if (connection == -1) { fprintf(stderr, "Child connection fail\n"); return connection; } struct rig_message msg = { {'H', 'O', 'W', 'D'}, {'Y', ' ', 'W', 'O', 'R', 'L', 'D', 0} }; - vscl_sock_send(connection, &msg); + int sent = vscl_sock_send(connection, &msg); + if (sent != 12) { + fprintf(stderr, "Failure to send all bytes: %i out of 12\n", sent); + return -1; + } + else { + printf("Sent all bytes.\n"); + } return vscl_sock_close(childed, &childsock); } From 80773e82b5045af6d8d5bf14be1d4b72f0bb4df0 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 12:44:30 -0500 Subject: [PATCH 13/34] Race condition guard in test --- lib/ipc/os.c | 12 ++++++++++++ lib/ipc/os.h | 2 ++ lib/ipc/sock.h | 1 - test/ipc/sock_communicating.c | 5 +++-- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/ipc/os.c b/lib/ipc/os.c index f25e9f9..3938451 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -63,6 +63,10 @@ int vscl_make_new_proc(const char* prog, const char* args) { return GetCurrentProcessId(); #else + fflush(stdout); + fflush(stderr); + fflush(stdin); + pid_t pid = fork(); switch (pid) { @@ -135,6 +139,14 @@ int vscl_make_new_proc(const char* prog, const char* args) { #endif } +void vscl_sleep(uint32_t s) { +#ifdef _WIN32 + Sleep(s * 1000) +#else + sleep(s); +#endif +} + #ifdef _WIN32 void vscl_winprint_error(const TCHAR* msg) { DWORD errcode = GetLastError(); diff --git a/lib/ipc/os.h b/lib/ipc/os.h index 5c3c670..6d30f1b 100644 --- a/lib/ipc/os.h +++ b/lib/ipc/os.h @@ -9,6 +9,7 @@ extern "C" { #endif #include "libtestrig_api.h" +#include #ifdef _WIN32 #else @@ -17,6 +18,7 @@ extern "C" { TESTRIG_API int vscl_get_sock_destination(char* dest); TESTRIG_API int vscl_make_new_proc(const char* prog, const char* args); +TESTRIG_API void vscl_sleep(uint32_t s); #ifdef _WIN32 TESTRIG_API void vscl_winprint_error(const TCHAR* msg); diff --git a/lib/ipc/sock.h b/lib/ipc/sock.h index 5955816..25d2128 100644 --- a/lib/ipc/sock.h +++ b/lib/ipc/sock.h @@ -11,7 +11,6 @@ extern "C" { #include #else #include "ipc/win_headers.h" -#define socklen_t socklen #endif // _WIN32 #include diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c index 9def558..abd9ec2 100644 --- a/test/ipc/sock_communicating.c +++ b/test/ipc/sock_communicating.c @@ -47,14 +47,14 @@ int main(int argc, char** argv) { vscl_byte_t buf[12] = { 0 }; #ifdef _WIN32 - int recvd = recv(accepted, buf, 12, MSG_PEEK); + int recvd = recv(acceptor, buf, 12, MSG_PEEK); #else int recvd = read(acceptor, buf, 12); #endif if (recvd != 12) { fprintf(stderr, "Failure to read full msg: %i out of 12\n", recvd); vscl_sock_close(parented, &sockaddr); - return recvd; + return (recvd == 0) ? -1 : recvd; } printf("Success: The message I got was %s\n", buf); @@ -66,6 +66,7 @@ int main(int argc, char** argv) { return vscl_sock_close(parented, &sockaddr); } else if (strncmp(argv[1], "child", 6) == 0) { + vscl_sleep(2); struct sockaddr_un childsock = { 0 }; int childed = vscl_sock_setup(&childsock); if (childed == INVALID_SOCKET) { fprintf(stderr, "Child sock maker fail\n"); return -1; } From b643d78531101f10e134a56091af2fd34375409a Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 13:02:35 -0500 Subject: [PATCH 14/34] Don't epicly fail because of a leading space --- lib/ipc/os.c | 4 ---- src/actions.c | 9 +++------ src/args.c | 17 ++++++++++------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/lib/ipc/os.c b/lib/ipc/os.c index 3938451..a4126bf 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -63,10 +63,6 @@ int vscl_make_new_proc(const char* prog, const char* args) { return GetCurrentProcessId(); #else - fflush(stdout); - fflush(stderr); - fflush(stdin); - pid_t pid = fork(); switch (pid) { diff --git a/src/actions.c b/src/actions.c index 8fd6505..d7d2417 100644 --- a/src/actions.c +++ b/src/actions.c @@ -44,18 +44,15 @@ int delegate_to_daemon(enum CLI_ACTION act) { if (!found) { printf("testrigd not running; creating new testrig process at "); - int pid = vscl_make_new_proc(PROG_NAME, "--detach --daemon"); + int pid = vscl_make_new_proc(PROG_NAME, "--detach daemon"); printf("%i\n", pid); } int conn = vscl_sock_connect(sock, &sockaddr); int try = 1; while (conn == -1 && try < NUM_MAX_RETRIES) { -#ifdef _WIN32 - Sleep(1000); -#else - sleep(1); -#endif + vscl_sleep(1); + try++; conn = vscl_sock_connect(sock, &sockaddr); } diff --git a/src/args.c b/src/args.c index 2f64631..172cfa5 100644 --- a/src/args.c +++ b/src/args.c @@ -44,13 +44,16 @@ int parse_flag(const char* flag, struct parsed_args* parsed) { int parse_act(const char* act, struct parsed_args* parsed) { int ret = 0; - if (!strncmp("daemon", act, 7)) { parsed->action = ACTION_DAEMON; ret = 1; } - else if (!strncmp("ident", act, 6)) { parsed->action = ACTION_IDENT; ret = 1; } - else if (!strncmp("status", act, 7)) { parsed->action = ACTION_STAT; ret = 1; } - else if (!strncmp("open", act, 5)) { parsed->action = ACTION_OPEN; ret = 1; } - else if (!strncmp("peek", act, 7)) { parsed->action = ACTION_REQUEST; ret = 1; } - else if (!strncmp("close", act, 6)) { parsed->action = ACTION_CLOSE; ret = 1; } - else if (!strncmp("help", act, 5)) { parsed->action = ACTION_HELP; ret = 1; } + char* lead_stripped = strstr(act, " "); + const char* actual = (lead_stripped == NULL) ? act : lead_stripped + 1; + + if (!strncmp("daemon", actual, 7)) { parsed->action = ACTION_DAEMON; ret = 1; } + else if (!strncmp("ident", actual, 6)) { parsed->action = ACTION_IDENT; ret = 1; } + else if (!strncmp("status", actual, 7)) { parsed->action = ACTION_STAT; ret = 1; } + else if (!strncmp("open", actual, 5)) { parsed->action = ACTION_OPEN; ret = 1; } + else if (!strncmp("peek", actual, 7)) { parsed->action = ACTION_REQUEST; ret = 1; } + else if (!strncmp("close", actual, 6)) { parsed->action = ACTION_CLOSE; ret = 1; } + else if (!strncmp("help", actual, 5)) { parsed->action = ACTION_HELP; ret = 1; } return ret; } From d00bf570de57c54dbbc4b5fbc9011983fcf1fe3d Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 13:12:33 -0500 Subject: [PATCH 15/34] Don't allow accidental writes to parent STDIN --- test/ipc/sock_communicating.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c index abd9ec2..ffa5ac4 100644 --- a/test/ipc/sock_communicating.c +++ b/test/ipc/sock_communicating.c @@ -5,8 +5,11 @@ static const char* TESTER_SOCK_NAME = "TEST_SOCK.rigsock"; // NOLINT int main(int argc, char** argv) { + if (argc < 2) { fprintf(stderr, "You must pass arguments to this test.\n"); return -1; } + printf("This was invoked with the following command line:\n"); printf("\t%s %s\n", argv[0], argv[1]); + fclose(stdin); char sockpath[108] = { 0 }; int retstat = vscl_get_sock_destination(sockpath); @@ -21,6 +24,10 @@ int main(int argc, char** argv) { strncpy(sockaddr.sun_path, sockpath, 108); if (strncmp(argv[1], "parent", 6) == 0) { + int forkstat = vscl_make_new_proc(argv[0], "child"); + if (forkstat == -1) { fprintf(stderr, "Failure to launch\n"); return forkstat; } + else { printf("New process was spawned with PID %i\n", forkstat); } + int parented = vscl_sock_setup(&sockaddr); if (parented == INVALID_SOCKET) { fprintf(stderr, "Parent sock maker fail\n"); return -1; } @@ -33,13 +40,8 @@ int main(int argc, char** argv) { return (!closestat) ? closestat : parentstat; } - // Race condition? - parentstat = vscl_make_new_proc(argv[0], "child"); - if (parentstat == -1) { fprintf(stderr, "Failure to launch\n"); return parentstat; } - else { printf("New process was spawned with PID %i\n", parentstat); } - int exitplz = 0; - socklen_t socklen = (socklen_t)sizeof(sockaddr); + socklen_t socklen = (socklen_t)sizeof(struct sockaddr); while (!exitplz) { int acceptor = accept(parented, (struct sockaddr*)&sockaddr, &socklen); if (acceptor == -1) { fprintf(stderr, "Accept epic fail\n"); continue; } @@ -66,10 +68,12 @@ int main(int argc, char** argv) { return vscl_sock_close(parented, &sockaddr); } else if (strncmp(argv[1], "child", 6) == 0) { - vscl_sleep(2); + vscl_sleep(5); // arbitrary + fflush(stdout); struct sockaddr_un childsock = { 0 }; int childed = vscl_sock_setup(&childsock); if (childed == INVALID_SOCKET) { fprintf(stderr, "Child sock maker fail\n"); return -1; } + else { printf("Child socket created at %s\n", childsock.sun_path); } int connection = vscl_sock_connect(childed, &sockaddr); if (connection == -1) { fprintf(stderr, "Child connection fail\n"); return connection; } @@ -86,4 +90,8 @@ int main(int argc, char** argv) { return vscl_sock_close(childed, &childsock); } + else { + fprintf(stderr, "Invalid token: %s\n", argv[1]); + return -1; + } } From db5732e9c6303f2feec879a9d2d72d004689b389 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 13:13:54 -0500 Subject: [PATCH 16/34] Windows Semicolon --- lib/ipc/os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ipc/os.c b/lib/ipc/os.c index a4126bf..610ae4f 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -137,7 +137,7 @@ int vscl_make_new_proc(const char* prog, const char* args) { void vscl_sleep(uint32_t s) { #ifdef _WIN32 - Sleep(s * 1000) + Sleep(s * 1000); #else sleep(s); #endif From 322ec9a4a41abb53282c8458f35d163a019bbfcd Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 13:38:35 -0500 Subject: [PATCH 17/34] Add ws2tcpip.h for Windows for socklen_t typedef --- lib/ipc/win_headers.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ipc/win_headers.h b/lib/ipc/win_headers.h index 070e898..1580cab 100644 --- a/lib/ipc/win_headers.h +++ b/lib/ipc/win_headers.h @@ -1,5 +1,6 @@ #ifdef _WIN32 #include #include +#include #include -#endif \ No newline at end of file +#endif From dd459152ada60166f5b4777d75e293f1593bb8b5 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 14:53:55 -0500 Subject: [PATCH 18/34] Zero-init proc info structs, improve test err msgs --- lib/ipc/os.c | 4 ++-- test/ipc/sock_communicating.c | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/ipc/os.c b/lib/ipc/os.c index 610ae4f..a85bc16 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -36,8 +36,8 @@ int vscl_get_sock_destination(char *dest) { int vscl_make_new_proc(const char* prog, const char* args) { #if _WIN32 - PROCESS_INFORMATION pi; - STARTUPINFO si; + PROCESS_INFORMATION pi = { 0 }; + STARTUPINFO si = { 0 }; char cmd[1024] = { 0 }; sprintf(cmd, "%s %s", prog, args); diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c index ffa5ac4..5d089c2 100644 --- a/test/ipc/sock_communicating.c +++ b/test/ipc/sock_communicating.c @@ -32,10 +32,15 @@ int main(int argc, char** argv) { if (parented == INVALID_SOCKET) { fprintf(stderr, "Parent sock maker fail\n"); return -1; } int parentstat = vscl_sock_bind(parented, &sockaddr); - if (parentstat == -1) { fprintf(stderr, "Sock binder fail\n"); return parentstat; } + if (parentstat == -1) { + fprintf(stderr, "Sock binder fail\n"); + int closestat = vscl_sock_close(parented, &sockaddr); + return (!closestat) ? closestat : parentstat; + } parentstat = vscl_sock_listen(parented, 1); if (parentstat == -1) { + fprintf(stderr, "Sock listener fail at sockpath %s\n", sockaddr.sun_path); int closestat = vscl_sock_close(parented, &sockaddr); return (!closestat) ? closestat : parentstat; } @@ -69,20 +74,27 @@ int main(int argc, char** argv) { } else if (strncmp(argv[1], "child", 6) == 0) { vscl_sleep(5); // arbitrary - fflush(stdout); + struct sockaddr_un childsock = { 0 }; int childed = vscl_sock_setup(&childsock); if (childed == INVALID_SOCKET) { fprintf(stderr, "Child sock maker fail\n"); return -1; } else { printf("Child socket created at %s\n", childsock.sun_path); } int connection = vscl_sock_connect(childed, &sockaddr); - if (connection == -1) { fprintf(stderr, "Child connection fail\n"); return connection; } + if (connection == -1) { + fprintf(stderr, "Child connection fail\n"); + vscl_sock_close(childed, &childsock); + int closestat = vscl_sock_close(childed, &sockaddr); + return (!closestat) ? closestat : connection; + } struct rig_message msg = { {'H', 'O', 'W', 'D'}, {'Y', ' ', 'W', 'O', 'R', 'L', 'D', 0} }; int sent = vscl_sock_send(connection, &msg); if (sent != 12) { fprintf(stderr, "Failure to send all bytes: %i out of 12\n", sent); - return -1; + vscl_sock_close(childed, &childsock); + int closestat = vscl_sock_close(childed, &sockaddr); + return (!closestat) ? closestat : -1; } else { printf("Sent all bytes.\n"); From 04fc006d18787b3234860b51f644a4462fa667a2 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 15:06:57 -0500 Subject: [PATCH 19/34] Improved error printers --- lib/epos2/connect.c | 14 +++++++------- lib/epos2/epos2.c | 8 ++++---- lib/epos2/epos2.h | 2 +- lib/epos2/identify.c | 8 ++++---- lib/epos2/manage.c | 2 +- lib/ipc/os.c | 16 +++++++++------- lib/ipc/os.h | 2 +- lib/ipc/pipe.c | 6 +++--- lib/ipc/sock.c | 12 ++++++------ src/daemon.c | 8 ++++---- test/ipc/CMakeLists.txt | 2 +- 11 files changed, 41 insertions(+), 39 deletions(-) diff --git a/lib/epos2/connect.c b/lib/epos2/connect.c index 9859e62..d91103b 100644 --- a/lib/epos2/connect.c +++ b/lib/epos2/connect.c @@ -7,7 +7,7 @@ #include "identify.h" static void vscl_failed_open_device(uint32_t error_code) { - vscl_print_error(error_code); + vscl_rig_perror(error_code); printf("Failed to open device with with following characteristics:\n"); } @@ -53,7 +53,7 @@ uint32_t vscl_initialize_devices(struct controller controllers_out[], void* hand error_code = vscl_clean_enable_device(&controllers_out[0], handles_out[0]); if (error_code != 0) { printf("While attempting to open gateway:\n\t"); - vscl_print_error(error_code); + vscl_rig_perror(error_code); return error_code; } @@ -77,7 +77,7 @@ uint32_t vscl_initialize_devices(struct controller controllers_out[], void* hand error_code = vscl_clean_enable_device(&controllers_out[i], handles_out[i]); if (error_code != 0) { printf("While attempting to open gateway:\n\t"); - vscl_print_error(error_code); + vscl_rig_perror(error_code); return error_code; } } @@ -100,7 +100,7 @@ uint32_t vscl_clean_enable_device(struct controller* controller, void* device_ha ret = VCS_ClearFault(device_handle, controller->node_id, &error_code); if (ret == 0) { printf("While clearing fault from %s at %s:\n\t", controller->name, controller->port); - vscl_print_error(error_code); + vscl_rig_perror(error_code); return error_code; } @@ -125,7 +125,7 @@ uint32_t vscl_close_device(struct controller* controller, void* device_handle) { if (ret == 0) { printf("While attempting to close device %s at node %ihh\n\t", controller->name, controller->node_id); - vscl_print_error(error_code); + vscl_rig_perror(error_code); return error_code; } @@ -156,7 +156,7 @@ uint32_t vscl_close_devices(struct controller controllers[], void* device_handle if (ret == 0) { printf("While closing subdevice %s at node %ihh:\n\t", controllers[i].name, controllers[i].node_id); - vscl_print_error(error_code); + vscl_rig_perror(error_code); return error_code; } @@ -169,7 +169,7 @@ uint32_t vscl_close_devices(struct controller controllers[], void* device_handle if (ret == 0) { printf("While closing gateway device %s at node %ihh:\n\t", controllers[0].name, controllers[0].node_id); - vscl_print_error(error_code); + vscl_rig_perror(error_code); return error_code; } diff --git a/lib/epos2/epos2.c b/lib/epos2/epos2.c index e16b80e..f286311 100644 --- a/lib/epos2/epos2.c +++ b/lib/epos2/epos2.c @@ -11,7 +11,7 @@ int vscl_decode_error(const uint32_t error_code, char* error_msg, vscl_byte_t ma return ret; } -int vscl_print_error(const uint32_t error_code) { +int vscl_rig_perror(const uint32_t error_code) { char msg[64] = { 0 }; int ret = vscl_decode_error(error_code, msg, 64); printf("ERROR 0x%X: %s\n", error_code, msg); @@ -24,7 +24,7 @@ uint32_t vscl_reset_device(void *device_handle, struct controller* controller_in uint32_t error_code = 0; int ret = VCS_ResetDevice(device_handle, controller_in->node_id, &error_code); if (ret == 0) { - vscl_print_error(error_code); + vscl_rig_perror(error_code); printf("Device failed to be reset: %s\n", controller_in->name); } @@ -47,7 +47,7 @@ uint32_t vscl_setup_can_gateway(struct controller controllers[3], void* handles[ error_code = vscl_initialize_devices(controllers, handles, 3); if (error_code != 0) { printf("When initializing multiple devices: "); - vscl_print_error(error_code); + vscl_rig_perror(error_code); return error_code; } @@ -60,7 +60,7 @@ uint32_t vscl_cleanup_testrig(struct controller controllers[3], void* handles[3] error_code = vscl_close_devices(controllers, handles, 3); if (error_code != 0) { printf("When cleaning up multiple devices: "); - vscl_print_error(error_code); + vscl_rig_perror(error_code); return error_code; } diff --git a/lib/epos2/epos2.h b/lib/epos2/epos2.h index 633d3cd..af56701 100644 --- a/lib/epos2/epos2.h +++ b/lib/epos2/epos2.h @@ -22,7 +22,7 @@ int TESTRIG_API vscl_decode_error(const uint32_t error_code, char* error_msg, vs /* * @brief Decode and print an error code's corresponding message. */ -int TESTRIG_API vscl_print_error(const uint32_t error_code); +int TESTRIG_API vscl_rig_perror(const uint32_t error_code); /* * @brief Reset a device. diff --git a/lib/epos2/identify.c b/lib/epos2/identify.c index fc6e54c..8b0935a 100644 --- a/lib/epos2/identify.c +++ b/lib/epos2/identify.c @@ -7,23 +7,23 @@ static void vscl_print_naming_error(vscl_byte_t error_code) { printf("While identifying device names:\n\t"); - vscl_print_error(error_code); + vscl_rig_perror(error_code); } static void vscl_print_protocol_ident_error(vscl_byte_t error_code, const char* name) { printf("While identifying device protocol stacks for device %s:\n\t", name); - vscl_print_error(error_code); + vscl_rig_perror(error_code); } static void vscl_print_interface_ident_error(vscl_byte_t error_code, const char* name, const char* protocol) { printf("While identifying device interface for device %s on protocol %s:\n\t", name, protocol); - vscl_print_error(error_code); + vscl_rig_perror(error_code); } static void vscl_print_port_ident_error(vscl_byte_t error_code, const char* name, const char* protocol, const char* iface) { printf("While identifying device interface for device %s on protocol %s and interface %s:\n\t", name, protocol, iface); - vscl_print_error(error_code); + vscl_rig_perror(error_code); } uint32_t vscl_ident_names(void) { diff --git a/lib/epos2/manage.c b/lib/epos2/manage.c index b86d5af..510f399 100644 --- a/lib/epos2/manage.c +++ b/lib/epos2/manage.c @@ -16,7 +16,7 @@ uint32_t vscl_abort(const struct controller* controller_in, void* device_handle) int ret = VCS_SetQuickStopState(device_handle, controller_in->node_id, &error_code); if (ret == 0) { - vscl_print_error(error_code); + vscl_rig_perror(error_code); printf("DANGER: Failed to abort rig operations!\n"); } else { diff --git a/lib/ipc/os.c b/lib/ipc/os.c index a85bc16..371a5ca 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -22,7 +22,7 @@ int vscl_get_sock_destination(char *dest) { errno_t retstat; retstat = getenv_s(&retvalue, usrtemp, 76, "TEMP"); - if (retvalue == 0 || retstat != 0) { perror("Failed to get TEMP"); return retstat; } + if (retvalue == 0 || retstat != 0) { vscl_os_perror("Failed to get TEMP"); return retstat; } strncpy(dest, usrtemp, retvalue); strncat(dest, "\\", 2); @@ -55,7 +55,7 @@ int vscl_make_new_proc(const char* prog, const char* args) { &pi ); - if (mkdetach == FALSE) { vscl_winprint_error("failed to detach"); return -1; } + if (mkdetach == FALSE) { vscl_os_perror("failed to detach"); return -1; } CloseHandle(&si); CloseHandle(&pi); @@ -67,12 +67,12 @@ int vscl_make_new_proc(const char* prog, const char* args) { switch (pid) { case -1: - perror("failed to fork off"); + vscl_os_perror("failed to fork off"); return -1; break; case 0: if (setsid() == -1) { - perror("failed to detach"); + vscl_os_perror("failed to detach"); return -1; } else { @@ -143,8 +143,8 @@ void vscl_sleep(uint32_t s) { #endif } +void vscl_os_perror(const char* preamble) { #ifdef _WIN32 -void vscl_winprint_error(const TCHAR* msg) { DWORD errcode = GetLastError(); TCHAR errmsg[256] = { 0 }; @@ -159,6 +159,8 @@ void vscl_winprint_error(const TCHAR* msg) { if (wides == 0) { printf("error while processing error\n"); } - wprintf(L"%s: %s", msg, errmsg); -} + wprintf(L"%s: %s", preamble, errmsg); +#else + perror(preamble); #endif +} \ No newline at end of file diff --git a/lib/ipc/os.h b/lib/ipc/os.h index 6d30f1b..a92d842 100644 --- a/lib/ipc/os.h +++ b/lib/ipc/os.h @@ -21,7 +21,7 @@ TESTRIG_API int vscl_make_new_proc(const char* prog, const char* args); TESTRIG_API void vscl_sleep(uint32_t s); #ifdef _WIN32 -TESTRIG_API void vscl_winprint_error(const TCHAR* msg); +TESTRIG_API void vscl_os_perror(const TCHAR* msg); #endif #ifdef __cplusplus diff --git a/lib/ipc/pipe.c b/lib/ipc/pipe.c index fecd5f3..193c8da 100644 --- a/lib/ipc/pipe.c +++ b/lib/ipc/pipe.c @@ -13,14 +13,14 @@ vscl_pipe_t vscl_create_pipes() { sattrs.lpSecurityDescriptor = NULL; if (!CreatePipe(&piper.child_read, &piper.child_write, &sattrs, 0)) - vscl_winprint_error("While creating child read pipe"); + vscl_os_perror("While creating child read pipe"); if (!SetHandleInformation(piper.child_read, HANDLE_FLAG_INHERIT, 0)) - vscl_winprint_error("While preventing child from taking parent pipe attributes"); + vscl_os_perror("While preventing child from taking parent pipe attributes"); #else int pipestat = pipe(piper.linux_fds); - if (pipestat == -1) { perror("While creating pipes"); } + if (pipestat == -1) { vscl_os_perror("While creating pipes"); } #endif diff --git a/lib/ipc/sock.c b/lib/ipc/sock.c index f776489..4f1ad70 100644 --- a/lib/ipc/sock.c +++ b/lib/ipc/sock.c @@ -42,11 +42,11 @@ int vscl_sock_setup(struct sockaddr_un* sockaddr_mut) { int wsa_result; wsa_result = WSAStartup(MAKEWORD(2, 2), &wsa_data); - if (wsa_result != 0) { perror("failed WSAStartup"); return -1; } + if (wsa_result != 0) { vscl_os_perror("failed WSAStartup"); return -1; } #endif // _WIN32 fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == INVALID_SOCKET) { perror("failed to create socket"); return -1; } + if (fd == INVALID_SOCKET) { vscl_os_perror("failed to create socket"); return -1; } path_set = (strncmp( sockaddr_mut->sun_path, blank, @@ -68,7 +68,7 @@ int vscl_sock_bind(const int fd, const struct sockaddr_un* sockaddr) { socklen = sizeof(*sockaddr); bindstat = bind(fd, (struct sockaddr*)sockaddr, socklen); - if (bindstat == -1) { perror("failed to bind socket"); } + if (bindstat == -1) { vscl_os_perror("failed to bind socket"); } return bindstat; } @@ -77,7 +77,7 @@ int vscl_sock_listen(const int fd, int max_backlog) { int listenstat; listenstat = listen(fd, max_backlog); - if (listenstat == -1) { perror("failed to set socket to listen"); } + if (listenstat == -1) { vscl_os_perror("failed to set socket to listen"); } return listenstat; } @@ -88,7 +88,7 @@ int vscl_sock_connect(const int fd, const struct sockaddr_un* sockaddr) { socklen = sizeof(*sockaddr); connstat = connect(fd, (struct sockaddr*)sockaddr, socklen); - if (connstat == -1) { perror("failed to connect to socket"); } + if (connstat == -1) { vscl_os_perror("failed to connect to socket"); } return connstat; } @@ -123,7 +123,7 @@ int vscl_sock_send(const int fd, struct rig_message* msg) { #else nbytes = write(fd, buf, 12); #endif - if (nbytes == -1) { perror("Clientside socket send error"); } + if (nbytes == -1) { vscl_os_perror("Clientside socket send error"); } return nbytes; } diff --git a/src/daemon.c b/src/daemon.c index efcfd72..0192120 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -46,7 +46,7 @@ static void interrupt_catcher(int sig, siginfo_t* info, [[ maybe_unused ]] void* static int deploy_interrupt_cleanup([[maybe_unused]] int sock, [[maybe_unused]] struct sockaddr_un* sockaddr) { #ifdef _WIN32 BOOL setted = SetConsoleCtrlHandler(interrupt_catcher, TRUE); - if (!setted) { vscl_winprint_error("daemon ctrl handler"); return 0; } + if (!setted) { vscl_os_perror("daemon ctrl handler"); return 0; } daemon_sockaddr = sockaddr; daemon_sock = sock; @@ -57,7 +57,7 @@ static int deploy_interrupt_cleanup([[maybe_unused]] int sock, [[maybe_unused]] act.sa_sigaction = &interrupt_catcher; int sigint_bound = sigaction(SIGINT, &act, NULL); - if (sigint_bound == -1) { perror("daemon signal capture"); return 0; } + if (sigint_bound == -1) { vscl_os_perror("daemon signal capture"); return 0; } return 1; #endif // _WIN32: Setup signal handler } // interrupt intercept maker @@ -140,7 +140,7 @@ int testrig_daemon(other_args* others) { DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_LISTENING; while (DAEMON_CURRENT_STATUS == TESTRIG_DAEMON_LISTENING) { int accepted = accept(sock, (struct sockaddr*)&sockaddr, &socksize); - if (accepted == -1) { perror("daemon accept failure"); continue; } + if (accepted == -1) { vscl_os_perror("daemon accept failure"); continue; } vscl_byte_t buf[12] = { 0 }; @@ -149,7 +149,7 @@ int testrig_daemon(other_args* others) { #else int recvd = read(accepted, buf, 12); #endif - if (recvd != 12) { perror("did not read full msg"); continue; } + if (recvd != 12) { vscl_os_perror("did not read full msg"); continue; } vscl_byte_t body[8] = { 0 }; for (uint8_t i = 4; i < 12; i++) { diff --git a/test/ipc/CMakeLists.txt b/test/ipc/CMakeLists.txt index 8a7e82b..6588307 100644 --- a/test/ipc/CMakeLists.txt +++ b/test/ipc/CMakeLists.txt @@ -15,4 +15,4 @@ function(make_ipc_test OUT_TGT_NAME IN_SOURCES) endfunction(make_ipc_test OUT_TGT_NAME IN_SOURCES) make_ipc_test(sock_naming "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") -make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "parent") +make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "parent") \ No newline at end of file From 6449d7697666e655d1f5412ff26fbebd00986130 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 15:10:48 -0500 Subject: [PATCH 20/34] Move new perror out of ifdef --- lib/ipc/os.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/ipc/os.h b/lib/ipc/os.h index a92d842..67f8477 100644 --- a/lib/ipc/os.h +++ b/lib/ipc/os.h @@ -19,10 +19,7 @@ extern "C" { TESTRIG_API int vscl_get_sock_destination(char* dest); TESTRIG_API int vscl_make_new_proc(const char* prog, const char* args); TESTRIG_API void vscl_sleep(uint32_t s); - -#ifdef _WIN32 -TESTRIG_API void vscl_os_perror(const TCHAR* msg); -#endif +TESTRIG_API void vscl_os_perror(const char* msg); #ifdef __cplusplus } // extern "C" From 96503402c05cefc8d95e8b41f07ae3dadb762bfd Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 15:17:52 -0500 Subject: [PATCH 21/34] Just use ANSI chars on windows perror --- lib/ipc/os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ipc/os.c b/lib/ipc/os.c index 371a5ca..b529364 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -159,7 +159,7 @@ void vscl_os_perror(const char* preamble) { if (wides == 0) { printf("error while processing error\n"); } - wprintf(L"%s: %s", preamble, errmsg); + printf("%s: %s", preamble, errmsg); #else perror(preamble); #endif From d2947298562f563f9656bc042d44749f9f21d4a4 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 15:25:11 -0500 Subject: [PATCH 22/34] Opening and closing a sock rq --- test/ipc/CMakeLists.txt | 3 ++- test/ipc/sock_communicating.c | 7 +++++-- test/ipc/sock_quickopening.c | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 test/ipc/sock_quickopening.c diff --git a/test/ipc/CMakeLists.txt b/test/ipc/CMakeLists.txt index 6588307..f66e8a1 100644 --- a/test/ipc/CMakeLists.txt +++ b/test/ipc/CMakeLists.txt @@ -15,4 +15,5 @@ function(make_ipc_test OUT_TGT_NAME IN_SOURCES) endfunction(make_ipc_test OUT_TGT_NAME IN_SOURCES) make_ipc_test(sock_naming "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") -make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "parent") \ No newline at end of file +make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "parent") +make_ipc_test(sock_quickopening "${CMAKE_CURRENT_LIST_DIR}/sock_quickopening.c") \ No newline at end of file diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c index 5d089c2..975f05f 100644 --- a/test/ipc/sock_communicating.c +++ b/test/ipc/sock_communicating.c @@ -23,13 +23,16 @@ int main(int argc, char** argv) { struct sockaddr_un sockaddr = { .sun_family = AF_UNIX, }; strncpy(sockaddr.sun_path, sockpath, 108); - if (strncmp(argv[1], "parent", 6) == 0) { + if (strncmp(argv[1], "parent", 7) == 0) { int forkstat = vscl_make_new_proc(argv[0], "child"); if (forkstat == -1) { fprintf(stderr, "Failure to launch\n"); return forkstat; } else { printf("New process was spawned with PID %i\n", forkstat); } int parented = vscl_sock_setup(&sockaddr); - if (parented == INVALID_SOCKET) { fprintf(stderr, "Parent sock maker fail\n"); return -1; } + if (parented == INVALID_SOCKET) { + fprintf(stderr, "Parent sock maker fail\n"); + return -1; + } int parentstat = vscl_sock_bind(parented, &sockaddr); if (parentstat == -1) { diff --git a/test/ipc/sock_quickopening.c b/test/ipc/sock_quickopening.c new file mode 100644 index 0000000..8af7cdf --- /dev/null +++ b/test/ipc/sock_quickopening.c @@ -0,0 +1,17 @@ +#include "ipc/sock.h" +#include "ipc/os.h" +#include + + +int main(int argc, char** argv) { + struct sockaddr_un sockaddr = { 0 }; + int sock = vscl_sock_setup(&sockaddr); + if (sock == INVALID_SOCKET) { vscl_os_perror("Socket quickopen fail: setup"); return -1; } + else { printf("Sock created for quickopen at %s\n", sockaddr.sun_path); } + + int bound = vscl_sock_bind(sock, &sockaddr); + if (bound == -1) { vscl_os_perror("Socket quickopen fail: bind"); return -1; } + + printf("Goodbye!\n"); + return vscl_sock_close(sock, &sockaddr); +} \ No newline at end of file From 384dc05c3e4a264765e0c6275aeafbc5977f1dc9 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Thu, 23 Apr 2026 10:15:51 -0500 Subject: [PATCH 23/34] Use the proper fd mate! --- test/ipc/sock_communicating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ipc/sock_communicating.c b/test/ipc/sock_communicating.c index 975f05f..f5cc441 100644 --- a/test/ipc/sock_communicating.c +++ b/test/ipc/sock_communicating.c @@ -92,7 +92,7 @@ int main(int argc, char** argv) { } struct rig_message msg = { {'H', 'O', 'W', 'D'}, {'Y', ' ', 'W', 'O', 'R', 'L', 'D', 0} }; - int sent = vscl_sock_send(connection, &msg); + int sent = vscl_sock_send(childed, &msg); if (sent != 12) { fprintf(stderr, "Failure to send all bytes: %i out of 12\n", sent); vscl_sock_close(childed, &childsock); From c34d7138e46cf221c168b92c291a4e81d753c94e Mon Sep 17 00:00:00 2001 From: JC Luna Date: Thu, 23 Apr 2026 15:28:16 -0500 Subject: [PATCH 24/34] Remove windows socklen ifdefs --- CMakeLists.txt | 7 +++++++ lib/ipc/sock.c | 5 ----- src/daemon.c | 8 +++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f3e2321..7f3a9f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") project(libtestrig LANGUAGES C) +include(CTest) include(target_copy_dll) include(target_output_to_bin) include(target_compile_warn_all) @@ -46,6 +47,12 @@ else() set(EposCmd-FOUND TRUE) endif() +if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") + message("-- Creating coverage reports in Debug mode.") + add_compile_options(-coverage) + add_link_options(-coverage) +endif() + add_library(libtestrig SHARED ${LIBTESTRIG_SOURCES}) target_compile_definitions(libtestrig PRIVATE COMPILING_TESTRIG_DLL) target_include_directories(libtestrig PUBLIC ${LIB_DIR}) diff --git a/lib/ipc/sock.c b/lib/ipc/sock.c index 4f1ad70..be8a658 100644 --- a/lib/ipc/sock.c +++ b/lib/ipc/sock.c @@ -6,11 +6,6 @@ #include "sock.h" #include "os.h" -#ifdef _WIN32 -// TODO: Evaluate if this is sufficient (it is honestly kind of smelly) -typedef int socklen_t; -#endif - int vscl_sock_genpath(char* sockpath) { int retstat; int baselen; diff --git a/src/daemon.c b/src/daemon.c index 0192120..5ba6c32 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -9,9 +9,7 @@ #include "ipc/ipc.h" #ifdef _WIN32 -#include -#include // holy cow there is some include order stuff with windows.h -typedef int socklen_t; +#include "ipc/win_headers.h" #else #include #include @@ -156,10 +154,10 @@ int testrig_daemon(other_args* others) { body[i - 4] = buf[i]; } - if (!strncmp("STATUS", body, 7)) { testrig_stat(NULL); } + if (!strncmp("STATUS", body, 7)) { testrig_stat(NULL); } else if (!strncmp("OPEN", body, 5)) { testrig_open(NULL); } else if (!strncmp("REQUEST", body, 7)) { testrig_peek(NULL); } - else if (!strncmp("CLOSE", body, 6)) { testrig_close(NULL); } + else if (!strncmp("CLOSE", body, 6)) { testrig_close(NULL); } else if (!strncmp("DOWN", body, 5)) { DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_CLEANING; } } From 9f5b358836078d779a142b7297e6a5458a484116 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Thu, 23 Apr 2026 15:47:10 -0500 Subject: [PATCH 25/34] Simple daemon interrupt test --- test/CMakeLists.txt | 17 ++++++++++++++++- test/cli/CMakeLists.txt | 1 + test/cli/daemon_interrupting.c | 24 ++++++++++++++++++++++++ test/ipc/CMakeLists.txt | 22 +++------------------- 4 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 test/cli/CMakeLists.txt create mode 100644 test/cli/daemon_interrupting.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d661971..6a0f0b8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,18 @@ enable_testing() -add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ipc") \ No newline at end of file +function(make_unit_test OUT_TGT_NAME IN_SOURCES) + if (${ARGC} GREATER 2) + set(_other_args ${ARGV2}) + else() + set(_other_args) + endif() + + add_executable(${OUT_TGT_NAME} ${IN_SOURCES}) + target_link_libraries(${OUT_TGT_NAME} PRIVATE libtestrig) + target_copy_dll(${OUT_TGT_NAME}) + target_compile_warn_all(${OUT_TGT_NAME}) + add_test(NAME "${OUT_TGT_NAME}_test" COMMAND $ ${_other_args}) +endfunction(make_unit_test OUT_TGT_NAME IN_SOURCES) + +add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ipc") +add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/cli") \ No newline at end of file diff --git a/test/cli/CMakeLists.txt b/test/cli/CMakeLists.txt new file mode 100644 index 0000000..4d8b940 --- /dev/null +++ b/test/cli/CMakeLists.txt @@ -0,0 +1 @@ +make_unit_test(daemon_interrupting "${CMAKE_CURRENT_LIST_DIR}/daemon_interrupting.c" $) \ No newline at end of file diff --git a/test/cli/daemon_interrupting.c b/test/cli/daemon_interrupting.c new file mode 100644 index 0000000..635496c --- /dev/null +++ b/test/cli/daemon_interrupting.c @@ -0,0 +1,24 @@ +#include +#include + +#include "ipc/os.h" + +int main(int argc, char** argv) { + if (argc < 2) { fprintf(stderr, "This test requires arguments.\n"); return -1; } + + int made = vscl_make_new_proc(argv[1], "daemon"); + vscl_sleep(2); + int made2 = vscl_make_new_proc(argv[1], "daemon down"); + vscl_sleep(1); + + char sockpath[108] = { 0 }; + int making_path = vscl_get_sock_destination(sockpath); + if (making_path) { fprintf(stderr, "Failed to get sock destination. Did an upstream test fail?\n"); return -1; } + + strncat(sockpath, "testrigd.sock", 15); + + FILE* potential_sock = fopen(sockpath, "r"); + int not_there = potential_sock == NULL; + + return (made != -1 && made2 != -1 && not_there) ? 0 : -1; +} \ No newline at end of file diff --git a/test/ipc/CMakeLists.txt b/test/ipc/CMakeLists.txt index f66e8a1..0dd74dc 100644 --- a/test/ipc/CMakeLists.txt +++ b/test/ipc/CMakeLists.txt @@ -1,19 +1,3 @@ -function(make_ipc_test OUT_TGT_NAME IN_SOURCES) - - if (${ARGC} GREATER 2) - set(_other_args ${ARGV2}) - else() - set(_other_args) - endif() - - add_executable(${OUT_TGT_NAME} ${IN_SOURCES}) - target_link_libraries(${OUT_TGT_NAME} PRIVATE libtestrig) - target_copy_dll(${OUT_TGT_NAME}) - target_compile_warn_all(${OUT_TGT_NAME}) - add_test(NAME "${OUT_TGT_NAME}_test" COMMAND $ ${_other_args}) - -endfunction(make_ipc_test OUT_TGT_NAME IN_SOURCES) - -make_ipc_test(sock_naming "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") -make_ipc_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "parent") -make_ipc_test(sock_quickopening "${CMAKE_CURRENT_LIST_DIR}/sock_quickopening.c") \ No newline at end of file +make_unit_test(sock_naming "${CMAKE_CURRENT_LIST_DIR}/sock_naming.c") +make_unit_test(sock_communicating "${CMAKE_CURRENT_LIST_DIR}/sock_communicating.c" "parent") +make_unit_test(sock_quickopening "${CMAKE_CURRENT_LIST_DIR}/sock_quickopening.c") \ No newline at end of file From de626d852f9666a94be3872e5b8c22c1d3a5715f Mon Sep 17 00:00:00 2001 From: JC Luna Date: Thu, 23 Apr 2026 23:31:16 -0500 Subject: [PATCH 26/34] Wrap in a string so it doesn't fail --- CMakeLists.txt | 4 ++-- CMakePresets.json | 1 + test/cli/daemon_interrupting.c | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f3a9f0..c5e9790 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ else() set(EposCmd-FOUND TRUE) endif() -if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") +if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") message("-- Creating coverage reports in Debug mode.") add_compile_options(-coverage) add_link_options(-coverage) @@ -65,4 +65,4 @@ if (WIN32) endif() add_subdirectory("${CMAKE_SOURCE_DIR}/src") -add_subdirectory("${CMAKE_SOURCE_DIR}/test") \ No newline at end of file +add_subdirectory("${CMAKE_SOURCE_DIR}/test") diff --git a/CMakePresets.json b/CMakePresets.json index f8acb73..91b68b2 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -15,6 +15,7 @@ "CMAKE_COLOR_DIAGNOSTICS": "ON" } }, + { "name": "windows-only", "hidden": true, diff --git a/test/cli/daemon_interrupting.c b/test/cli/daemon_interrupting.c index 635496c..0362d01 100644 --- a/test/cli/daemon_interrupting.c +++ b/test/cli/daemon_interrupting.c @@ -1,5 +1,5 @@ #include -#include +#include #include "ipc/os.h" @@ -21,4 +21,4 @@ int main(int argc, char** argv) { int not_there = potential_sock == NULL; return (made != -1 && made2 != -1 && not_there) ? 0 : -1; -} \ No newline at end of file +} From 29b86a6e5a6477377359f18d29ad4e6f4dece89a Mon Sep 17 00:00:00 2001 From: JC Luna Date: Fri, 24 Apr 2026 23:09:51 -0500 Subject: [PATCH 27/34] Fix newproc function --- lib/ipc/os.c | 4 ++-- test/cli/daemon_interrupting.c | 36 +++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/lib/ipc/os.c b/lib/ipc/os.c index b529364..9a5491a 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -110,7 +110,7 @@ int vscl_make_new_proc(const char* prog, const char* args) { size_t argnlen = vscl_strinterlen(argn, argn1); argnlen = (argnlen == 0) ? 64 : argnlen; - strncpy(argnstr, argn1, argnlen); + strncpy(argnstr, argn1 + 1, argnlen); strncpy(argv[n], argnstr, strlen(argnstr) + 1); argn1 = argn; @@ -163,4 +163,4 @@ void vscl_os_perror(const char* preamble) { #else perror(preamble); #endif -} \ No newline at end of file +} diff --git a/test/cli/daemon_interrupting.c b/test/cli/daemon_interrupting.c index 0362d01..326b8d2 100644 --- a/test/cli/daemon_interrupting.c +++ b/test/cli/daemon_interrupting.c @@ -6,19 +6,33 @@ int main(int argc, char** argv) { if (argc < 2) { fprintf(stderr, "This test requires arguments.\n"); return -1; } + printf("Starting the daemon...\n"); int made = vscl_make_new_proc(argv[1], "daemon"); - vscl_sleep(2); - int made2 = vscl_make_new_proc(argv[1], "daemon down"); - vscl_sleep(1); - - char sockpath[108] = { 0 }; - int making_path = vscl_get_sock_destination(sockpath); - if (making_path) { fprintf(stderr, "Failed to get sock destination. Did an upstream test fail?\n"); return -1; } - strncat(sockpath, "testrigd.sock", 15); + if (made != 0 && made != -1) { + printf("Yielding for init...\n"); + vscl_sleep(5); + + printf("Killing the daemon...\n"); + int made2 = vscl_make_new_proc(argv[1], "daemon down"); + vscl_sleep(2); + + char sockpath[108] = { 0 }; + int making_path = vscl_get_sock_destination(sockpath); + if (making_path) { fprintf(stderr, + "Failed to get sock destination for your platform. Did an upstream test fail?\n"); return -1; } - FILE* potential_sock = fopen(sockpath, "r"); - int not_there = potential_sock == NULL; + strncat(sockpath, "testrigd.sock", 15); - return (made != -1 && made2 != -1 && not_there) ? 0 : -1; + FILE* potential_sock = fopen(sockpath, "r"); + int not_there = potential_sock == NULL; + + return (made != -1 && made2 != -1 && not_there) ? 0 : -1; + } + else if (made == -1) { + vscl_os_perror("Could not make the process.\n"); + return -1; + } + + return 0; } From 28962dad9393595fb0a491267201d9b7a95baee1 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Fri, 24 Apr 2026 23:15:11 -0500 Subject: [PATCH 28/34] More explict non-constness --- lib/ipc/os.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ipc/os.c b/lib/ipc/os.c index 9a5491a..1d39440 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -84,7 +84,7 @@ int vscl_make_new_proc(const char* prog, const char* args) { strncpy(argv[0], prog, strlen(prog) + 1); argv[1] = (char*)calloc(64, 1); - char* arg1 = strstr(args, " "); + const char* arg1 = strstr(args, " "); if (arg1 == NULL) { strncpy(argv[1], args, strlen(args) + 1); } @@ -95,8 +95,8 @@ int vscl_make_new_proc(const char* prog, const char* args) { strncpy(interstr, args, interlen); strncpy(argv[1], interstr, strlen(interstr) + 1); - char* argn = strstr(arg1, " "); - char* argn1 = arg1; + char* argn = (char*)strstr(arg1, " "); + char* argn1 = (char*)arg1; while (argn != NULL) { num_args++; if (num_args > sizeof_argv) { From af4ff36a16d934bc94a2fe2ce7e375ca9fffb0a1 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Sat, 25 Apr 2026 01:51:24 -0500 Subject: [PATCH 29/34] Silence another strstr discarded qual warn + aliasing libs --- CMakeLists.txt | 4 ++++ src/CMakeLists.txt | 9 +++++++-- src/args.c | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c5e9790..0fe11b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,10 +59,14 @@ target_include_directories(libtestrig PUBLIC ${LIB_DIR}) target_link_libraries(libtestrig PUBLIC EposCmd) target_compile_warn_all(libtestrig) target_output_to_bin(libtestrig) +set_target_properties(libtestrig + PROPERTIES VERIFY_INTERFACE_HEADER_SETS ON) if (WIN32) target_link_libraries(libtestrig PUBLIC Ws2_32 Kernel32) endif() +add_library(vscl::testrig::lib ALIAS libtestrig) + add_subdirectory("${CMAKE_SOURCE_DIR}/src") add_subdirectory("${CMAKE_SOURCE_DIR}/test") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d78669a..d7d6286 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,12 @@ set(TESTRIG_SOURCES "${CMAKE_CURRENT_LIST_DIR}/daemon.c") add_executable(testrig ${TESTRIG_SOURCES}) -target_link_libraries(testrig PRIVATE libtestrig) +target_link_libraries(testrig PRIVATE vscl::testrig::lib) target_include_directories(testrig PRIVATE ${LIB_DIR}) target_compile_warn_all(testrig) -target_output_to_bin(testrig) \ No newline at end of file +target_output_to_bin(testrig) +set_target_properties(testrig + PROPERTIES VERIFY_INTERFACE_HEADER_SETS ON) + +add_executable(vscl::testrig::cli ALIAS testrig) + diff --git a/src/args.c b/src/args.c index 172cfa5..7ca7fe5 100644 --- a/src/args.c +++ b/src/args.c @@ -44,7 +44,7 @@ int parse_flag(const char* flag, struct parsed_args* parsed) { int parse_act(const char* act, struct parsed_args* parsed) { int ret = 0; - char* lead_stripped = strstr(act, " "); + const char* lead_stripped = strstr(act, " "); const char* actual = (lead_stripped == NULL) ? act : lead_stripped + 1; if (!strncmp("daemon", actual, 7)) { parsed->action = ACTION_DAEMON; ret = 1; } From 89aabf2a04875e8917d207cedd94652c90796dee Mon Sep 17 00:00:00 2001 From: JC Luna Date: Sat, 25 Apr 2026 02:03:39 -0500 Subject: [PATCH 30/34] Don't output an error when canceling in some cases --- src/daemon.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/daemon.c b/src/daemon.c index 5ba6c32..8d0ba9f 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -26,7 +26,7 @@ static SOCKET daemon_sock; BOOL WINAPI interrupt_catcher(DWORD ctrl_type) { if (ctrl_type == CTRL_C_EVENT) { - DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_STOPPED; + DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_CLEANING; printf("Stopping!\n"); vscl_sock_close(daemon_sock, daemon_sockaddr); return TRUE; @@ -37,7 +37,7 @@ BOOL WINAPI interrupt_catcher(DWORD ctrl_type) { #else static void interrupt_catcher(int sig, siginfo_t* info, [[ maybe_unused ]] void* ucontext) { if (sig != SIGINT || info->si_signo != SIGINT) { return; } - DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_STOPPED; + DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_CLEANING; } #endif // _WIN32: Clean Ctrl+C handlers @@ -113,7 +113,7 @@ int testrig_daemon(other_args* others) { return 0; } else if (sought) { - fprintf(stderr, "error: daemon already running\n"); + fprintf(stderr, "Error: Daemon already running\n"); return -1; } @@ -134,11 +134,16 @@ int testrig_daemon(other_args* others) { return -1; } - printf("waiting for connection...\n"); + printf("Waiting for connection...\n"); DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_LISTENING; while (DAEMON_CURRENT_STATUS == TESTRIG_DAEMON_LISTENING) { int accepted = accept(sock, (struct sockaddr*)&sockaddr, &socksize); - if (accepted == -1) { vscl_os_perror("daemon accept failure"); continue; } + if (accepted == -1) { + if (DAEMON_CURRENT_STATUS != TESTRIG_DAEMON_CLEANING) + vscl_os_perror("Daemon accept failure"); + + continue; + } vscl_byte_t buf[12] = { 0 }; @@ -147,17 +152,24 @@ int testrig_daemon(other_args* others) { #else int recvd = read(accepted, buf, 12); #endif - if (recvd != 12) { vscl_os_perror("did not read full msg"); continue; } + if (recvd != 12) { + if (DAEMON_CURRENT_STATUS == TESTRIG_DAEMON_LISTENING + || DAEMON_CURRENT_STATUS == TESTRIG_DAEMON_CONNECTED) { + vscl_os_perror("Did not read full msg"); + } + + continue; + } vscl_byte_t body[8] = { 0 }; for (uint8_t i = 4; i < 12; i++) { body[i - 4] = buf[i]; } - if (!strncmp("STATUS", body, 7)) { testrig_stat(NULL); } + if (!strncmp("STATUS", body, 7)) { testrig_stat(NULL); } else if (!strncmp("OPEN", body, 5)) { testrig_open(NULL); } else if (!strncmp("REQUEST", body, 7)) { testrig_peek(NULL); } - else if (!strncmp("CLOSE", body, 6)) { testrig_close(NULL); } + else if (!strncmp("CLOSE", body, 6)) { testrig_close(NULL); } else if (!strncmp("DOWN", body, 5)) { DAEMON_CURRENT_STATUS = TESTRIG_DAEMON_CLEANING; } } From ae68c57c4d191025d28f3b3aa6ce76c135f49692 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Sat, 25 Apr 2026 02:07:10 -0500 Subject: [PATCH 31/34] Consistent capitalization in printed msgs --- src/actions.c | 8 ++++---- src/daemon.c | 4 ++-- src/main.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/actions.c b/src/actions.c index d7d2417..cc7f540 100644 --- a/src/actions.c +++ b/src/actions.c @@ -43,7 +43,7 @@ int delegate_to_daemon(enum CLI_ACTION act) { int found = seek_daemon(&sockaddr); if (!found) { - printf("testrigd not running; creating new testrig process at "); + printf("testrigd not running; Creating new testrig process at "); int pid = vscl_make_new_proc(PROG_NAME, "--detach daemon"); printf("%i\n", pid); } @@ -58,7 +58,7 @@ int delegate_to_daemon(enum CLI_ACTION act) { } if (try >= NUM_MAX_RETRIES) { - fprintf(stderr, "failed to connect after %i retries", NUM_MAX_RETRIES); + fprintf(stderr, "Failed to connect after %i retries", NUM_MAX_RETRIES); return -1; } @@ -121,7 +121,7 @@ int testrig_ident(other_args* others) { return 0; } else { - fprintf(stderr, "error: the arguments passed to ident could not be parsed\n"); + fprintf(stderr, "Error: The arguments passed to ident could not be parsed\n"); return 1; } } @@ -156,7 +156,7 @@ int testrig_peek([[maybe_unused]] other_args* others) { if (setup == -1) { return 1; } int not_sought = seek_daemon(&daemon_sockaddr); - if (not_sought) { printf("not found"); vscl_sock_close(setup, &sockaddr); return 1; } + if (not_sought) { printf("Not found\n"); vscl_sock_close(setup, &sockaddr); return 1; } int conn = vscl_sock_connect(setup, &daemon_sockaddr); if (conn == -1) { return 1; } diff --git a/src/daemon.c b/src/daemon.c index 8d0ba9f..f5037d3 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -44,7 +44,7 @@ static void interrupt_catcher(int sig, siginfo_t* info, [[ maybe_unused ]] void* static int deploy_interrupt_cleanup([[maybe_unused]] int sock, [[maybe_unused]] struct sockaddr_un* sockaddr) { #ifdef _WIN32 BOOL setted = SetConsoleCtrlHandler(interrupt_catcher, TRUE); - if (!setted) { vscl_os_perror("daemon ctrl handler"); return 0; } + if (!setted) { vscl_os_perror("Daemon ctrl handler"); return 0; } daemon_sockaddr = sockaddr; daemon_sock = sock; @@ -55,7 +55,7 @@ static int deploy_interrupt_cleanup([[maybe_unused]] int sock, [[maybe_unused]] act.sa_sigaction = &interrupt_catcher; int sigint_bound = sigaction(SIGINT, &act, NULL); - if (sigint_bound == -1) { vscl_os_perror("daemon signal capture"); return 0; } + if (sigint_bound == -1) { vscl_os_perror("Daemon signal capture"); return 0; } return 1; #endif // _WIN32: Setup signal handler } // interrupt intercept maker diff --git a/src/main.c b/src/main.c index b4f74ed..8e768c9 100644 --- a/src/main.c +++ b/src/main.c @@ -30,7 +30,7 @@ int main(int argc, char** argv) { } if (parsed.fun == NULL) { - printf("unimplemented action\n"); + printf("Unimplemented action\n"); } else if (ret == 0) { ret = parsed.fun(&others); From 70a372b0d9a4355902bf35473f00e75ede5d2c2b Mon Sep 17 00:00:00 2001 From: JC Luna Date: Sat, 25 Apr 2026 02:10:35 -0500 Subject: [PATCH 32/34] INVALID_SOCKET define to sock.h --- lib/ipc/os.h | 5 ----- lib/ipc/sock.h | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/ipc/os.h b/lib/ipc/os.h index 67f8477..3460930 100644 --- a/lib/ipc/os.h +++ b/lib/ipc/os.h @@ -11,11 +11,6 @@ extern "C" { #include "libtestrig_api.h" #include -#ifdef _WIN32 -#else -#define INVALID_SOCKET -1 -#endif - TESTRIG_API int vscl_get_sock_destination(char* dest); TESTRIG_API int vscl_make_new_proc(const char* prog, const char* args); TESTRIG_API void vscl_sleep(uint32_t s); diff --git a/lib/ipc/sock.h b/lib/ipc/sock.h index 25d2128..809e474 100644 --- a/lib/ipc/sock.h +++ b/lib/ipc/sock.h @@ -9,6 +9,8 @@ extern "C" { #include #include #include + +#define INVALID_SOCKET -1 #else #include "ipc/win_headers.h" #endif // _WIN32 From a8111d71280a8d501b4d97f1659f666cf808ab2d Mon Sep 17 00:00:00 2001 From: JC Luna Date: Sat, 25 Apr 2026 17:14:20 -0500 Subject: [PATCH 33/34] Linux piper impl --- lib/ipc/pipe.c | 22 +++++++++++++++++----- lib/ipc/pipe.h | 9 +++++---- lib/ipc/sock.c | 10 +++++----- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/lib/ipc/pipe.c b/lib/ipc/pipe.c index 193c8da..2384371 100644 --- a/lib/ipc/pipe.c +++ b/lib/ipc/pipe.c @@ -17,20 +17,32 @@ vscl_pipe_t vscl_create_pipes() { if (!SetHandleInformation(piper.child_read, HANDLE_FLAG_INHERIT, 0)) vscl_os_perror("While preventing child from taking parent pipe attributes"); - #else - int pipestat = pipe(piper.linux_fds); + int pipefd[2] = { 0 }; + int pipestat = pipe(pipefd); if (pipestat == -1) { vscl_os_perror("While creating pipes"); } -#endif + piper.read_fd = pipefd[0]; + piper.write_fd = pipefd[1]; +#endif return piper; } -int vscl_read_pipe(vscl_pipe_t* pipe, vscl_byte_t* buf) { +int vscl_read_pipe(vscl_pipe_t* pipe, vscl_byte_t buf[], size_t nbytes) { +#if _WIN32 return 0; +#else + size_t read_actual = read(pipe->read_fd, buf, nbytes); + return (read_actual == nbytes) ? 0 : -1; +#endif } -int vscl_write_pipe(vscl_pipe_t* pipe, vscl_byte_t* buf) { +int vscl_write_pipe(vscl_pipe_t* pipe, vscl_byte_t buf[], size_t nbytes) { +#if _WIN32 return 0; +#else + size_t write_actual = write(pipe->write_fd, buf, nbytes); + return (write_actual == nbytes) ? 0 : -1; +#endif } diff --git a/lib/ipc/pipe.h b/lib/ipc/pipe.h index 92d0236..7e288a5 100644 --- a/lib/ipc/pipe.h +++ b/lib/ipc/pipe.h @@ -14,16 +14,17 @@ extern "C" { typedef struct { #ifdef _WIN32 - HANDLE child_write; HANDLE child_read; + HANDLE child_write; #else - int linux_fds[2]; + int read_fd; + int write_fd; #endif } vscl_pipe_t; TESTRIG_API vscl_pipe_t vscl_create_pipes(void); -TESTRIG_API int vscl_read_pipe(vscl_pipe_t* pipe, vscl_byte_t* buf); -TESTRIG_API int vscl_write_pipe(vscl_pipe_t* pipe, vscl_byte_t* buf); +TESTRIG_API int vscl_read_pipe(vscl_pipe_t* pipe, vscl_byte_t buf[], size_t nbytes); +TESTRIG_API int vscl_write_pipe(vscl_pipe_t* pipe, vscl_byte_t buf[], size_t nbytes); #ifdef __cplusplus } // extern "C" diff --git a/lib/ipc/sock.c b/lib/ipc/sock.c index be8a658..96942fd 100644 --- a/lib/ipc/sock.c +++ b/lib/ipc/sock.c @@ -37,11 +37,11 @@ int vscl_sock_setup(struct sockaddr_un* sockaddr_mut) { int wsa_result; wsa_result = WSAStartup(MAKEWORD(2, 2), &wsa_data); - if (wsa_result != 0) { vscl_os_perror("failed WSAStartup"); return -1; } + if (wsa_result != 0) { vscl_os_perror("Failed WSAStartup"); return -1; } #endif // _WIN32 fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == INVALID_SOCKET) { vscl_os_perror("failed to create socket"); return -1; } + if (fd == INVALID_SOCKET) { vscl_os_perror("Failed to create socket"); return -1; } path_set = (strncmp( sockaddr_mut->sun_path, blank, @@ -63,7 +63,7 @@ int vscl_sock_bind(const int fd, const struct sockaddr_un* sockaddr) { socklen = sizeof(*sockaddr); bindstat = bind(fd, (struct sockaddr*)sockaddr, socklen); - if (bindstat == -1) { vscl_os_perror("failed to bind socket"); } + if (bindstat == -1) { vscl_os_perror("Failed to bind socket"); } return bindstat; } @@ -72,7 +72,7 @@ int vscl_sock_listen(const int fd, int max_backlog) { int listenstat; listenstat = listen(fd, max_backlog); - if (listenstat == -1) { vscl_os_perror("failed to set socket to listen"); } + if (listenstat == -1) { vscl_os_perror("Failed to set socket to listen"); } return listenstat; } @@ -83,7 +83,7 @@ int vscl_sock_connect(const int fd, const struct sockaddr_un* sockaddr) { socklen = sizeof(*sockaddr); connstat = connect(fd, (struct sockaddr*)sockaddr, socklen); - if (connstat == -1) { vscl_os_perror("failed to connect to socket"); } + if (connstat == -1) { vscl_os_perror("Failed to connect to socket"); } return connstat; } From c976cf61cd68dcfcb04922e59a90638b5f1a3f25 Mon Sep 17 00:00:00 2001 From: JC Luna Date: Sun, 26 Apr 2026 01:40:44 -0500 Subject: [PATCH 34/34] Explict set last arg passed to execv to NULL --- lib/ipc/os.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/ipc/os.c b/lib/ipc/os.c index 1d39440..8f85906 100644 --- a/lib/ipc/os.c +++ b/lib/ipc/os.c @@ -118,6 +118,13 @@ int vscl_make_new_proc(const char* prog, const char* args) { } } + num_args++; + if (num_args > sizeof_argv) { + sizeof_argv *= 2; + argv = (char**)realloc(argv, sizeof_argv * sizeof(char*)); + } + + argv[num_args - 1] = NULL; execv(prog, argv); for (size_t i = 0; i < num_args; i++) {