From 60047ca5ce17b0eee0dbdff41d8d5e6c40d862e4 Mon Sep 17 00:00:00 2001 From: WHC Date: Sun, 11 Oct 2026 21:54:32 +0800 Subject: [PATCH] the session readers use getline(3), which a Windows CRT does not have Building the Windows TUI by hand -- the first local build since the CI file went away -- stopped in src/tools/session_tools.c: `getline` was an implicit declaration there, which this GCC treats as an error. src/session.c had a private fgetc() shim for exactly that; the session-list scan is newer and used the POSIX call directly, and only the Windows build notices. The shim moves to os_compat as os_getline(): getline(3) itself on Unix, the fgetc() loop on Windows, one prototype in the header so a caller reads the same everywhere. src/session.c drops its copy and calls it; the scan does too (its `ssize_t` becomes `long long`, which Windows has). make check is green on Linux, the Windows cross build now finishes and packages (dist/cst-agent-0.9.7-windows-x86_64.zip plus the NSIS setup), and the static Linux tarball was rebuilt with it. --- include/os_compat.h | 8 ++++++++ src/os_compat.c | 37 +++++++++++++++++++++++++++++++++++++ src/session.c | 36 ++---------------------------------- src/tools/session_tools.c | 4 ++-- 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/include/os_compat.h b/include/os_compat.h index 3c87d01..df64c61 100644 --- a/include/os_compat.h +++ b/include/os_compat.h @@ -2,6 +2,7 @@ #define CST_OS_COMPAT_H #include +#include #include #ifdef __cplusplus @@ -12,6 +13,13 @@ extern "C" { #define OS_PATH_MAX 4096 #endif +/* --- text --- */ +/* One line of a file into *lineptr, growing it as needed: POSIX getline(3), + * which a MinGW CRT does not have (the session file readers used it directly + * and only the Windows build noticed). Returns the number of bytes read -- 0 + * for an empty line -- or -1 at the end of the file. */ +long long os_getline(char **lineptr, size_t *n, FILE *stream); + /* --- path --- */ int os_path_is_abs(const char *p); /* Join with native separator; out always uses '/' on Unix and '\\' on Win for diff --git a/src/os_compat.c b/src/os_compat.c index b66fdbf..7a46401 100644 --- a/src/os_compat.c +++ b/src/os_compat.c @@ -1217,3 +1217,40 @@ int unsetenv(const char *name) { } #endif /* _WIN32 */ + +/* getline(3) itself where the libc has it; the same thing spelled out with + * fgetc() where it does not (Windows), so the callers read the same on every + * platform. */ +long long os_getline(char **lineptr, size_t *n, FILE *stream) { +#ifndef _WIN32 + return (long long)getline(lineptr, n, stream); +#else + if (!lineptr || !n || !stream) + return -1; + if (!*lineptr || *n == 0) { + *n = 256; + *lineptr = (char *)malloc(*n); + if (!*lineptr) + return -1; + } + size_t len = 0; + int c = 0; + while ((c = fgetc(stream)) != EOF) { + if (len + 2 > *n) { + const size_t nn = (*n) * 2; + char *nb = (char *)realloc(*lineptr, nn); + if (!nb) + return -1; + *lineptr = nb; + *n = nn; + } + (*lineptr)[len++] = (char)c; + if (c == '\n') + break; + } + if (len == 0 && c == EOF) + return -1; + (*lineptr)[len] = 0; + return (long long)len; +#endif +} diff --git a/src/session.c b/src/session.c index 5b0ede9..b6ae38a 100644 --- a/src/session.c +++ b/src/session.c @@ -15,39 +15,7 @@ #include #include -#ifdef _WIN32 -typedef long long cst_ssize_t; -static cst_ssize_t cst_getline(char **lineptr, size_t *n, FILE *stream) { - if (!lineptr || !n || !stream) - return -1; - if (!*lineptr || *n == 0) { - *n = 256; - *lineptr = (char *)malloc(*n); - if (!*lineptr) - return -1; - } - size_t len = 0; - int c = 0; - while ((c = fgetc(stream)) != EOF) { - if (len + 2 > *n) { - size_t nn = (*n) * 2; - char *nb = (char *)realloc(*lineptr, nn); - if (!nb) - return -1; - *lineptr = nb; - *n = nn; - } - (*lineptr)[len++] = (char)c; - if (c == '\n') - break; - } - if (len == 0 && c == EOF) - return -1; - (*lineptr)[len] = 0; - return (cst_ssize_t)len; -} -#define getline cst_getline -#endif +#include "os_compat.h" struct cst_session { char path[4096]; @@ -158,7 +126,7 @@ static void load_existing(cst_session_t *s) { return; char *line = NULL; size_t cap = 0; - while (getline(&line, &cap, rp) != -1) { + while (os_getline(&line, &cap, rp) != -1) { cJSON *o = cJSON_Parse(line); if (!o || !cJSON_IsObject(o)) { cJSON_Delete(o); diff --git a/src/tools/session_tools.c b/src/tools/session_tools.c index 2c42556..df1ff9b 100644 --- a/src/tools/session_tools.c +++ b/src/tools/session_tools.c @@ -121,8 +121,8 @@ int cst_tool_session_search(const cst_tool_ctx_t *ctx, const ctl_tool_call_t *c, char *line = NULL; size_t cap = 0; cst_buf_t one = {0}; - ssize_t got; - while ((got = getline(&line, &cap, fp)) > 0) { + long long got; + while ((got = os_getline(&line, &cap, fp)) > 0) { lineno++; scanned_bytes += got; /* A tool output line can be megabytes (a whole file read back): such a