From 1e1899158e80933f46b8f824c8029654472ec6bc Mon Sep 17 00:00:00 2001 From: JC Luna Date: Wed, 22 Apr 2026 09:27:36 -0500 Subject: [PATCH 01/22] 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 02/22] 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 03/22] 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 04/22] 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 05/22] 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 06/22] 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 07/22] 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 08/22] 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 09/22] 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 10/22] 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 11/22] 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 12/22] 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 13/22] 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 14/22] 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 15/22] 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 16/22] 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 17/22] 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 18/22] 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 19/22] 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 20/22] 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 21/22] 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 22/22] 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) {