anntp

a nntp implementation in pure C99
Log | Files | Refs | README | LICENSE

commit cd3aeedbed21357799097326623b488963ee63b2
parent d44cf21f1126a13920da529945a697174dc0d671
Author: Mario Rosell R. Martinez <mario@mariorosell.es>
Date:   Sat, 28 Mar 2026 21:44:33 +0100

anntp_overview: Add anntp_overview

Diffstat:
Manntp.h | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)

diff --git a/anntp.h b/anntp.h @@ -195,7 +195,8 @@ ANNTP_API ssize_t anntp_write(AnntpConnection* conn, const uchar_t* buf ANNTP_API int anntp_group(AnntpConnection* conn, const char* group, AnntpGroup* out_group); ANNTP_API ssize_t anntp_article(AnntpConnection*, size_t num, AnntpArticle* out_art); ANNTP_API void anntp_article_free(AnntpArticle* art); -ANNTP_API int anntp_article_cb(AnntpConnection*, size_t n, AnntpLineCb cb, void* extra); +ANNTP_API int anntp_article_cb(AnntpConnection* cv, size_t n, AnntpLineCb cb, void* extra); +ANNTP_API ssize_t anntp_overview(AnntpConnection* cv, size_t start, size_t end, AnntpOverview* ov); ANNTP_API ssize_t anntp_write_all(AnntpConnection* conn, const uchar_t* buf, size_t bufsize); ANNTP_API ssize_t anntp_writeline(AnntpConnection* conn, const char* buf); ANNTP_API ssize_t anntp_readline(AnntpConnection* conn, char* buf, size_t maxlen); @@ -304,6 +305,88 @@ cleanup: return NULL; } +ssize_t +anntp_overview(AnntpConnection* cv, size_t start, size_t end, AnntpOverview* ov) +{ + if (!cv || !ov || start > end) + return ANNTPE(ANE_PARAMS); + + char cmd[ANNTP_BUFSIZE]; + char line[ANNTP_BUFSIZE]; + + memset(ov, 0, sizeof(*ov)); + + snprintf(cmd, sizeof(cmd), "XOVER %zu-%zu", start, end); + + if (anntp_writeline(cv, cmd) <= 0) + return ANNTPE(ANE_IO); + + ssize_t r = anntp_readline(cv, line, sizeof(line)); + if (r <= 0) + return ANNTPE(ANE_IO); + + /* expect 224 */ + if (strncmp(line, "224", 3) != 0) + return ANNTPE(ANE_PROTO); + + size_t cap = 16; + ov->lines = (char**)ANNTP_MALLOC(sizeof(char*) * cap); + if (!ov->lines) + return ANNTPE(ANE_IO); + + size_t count = 0; + + for (;;) { + r = anntp_readline(cv, line, sizeof(line)); + if (r <= 0) + goto error; + + /* end */ + if (strcmp(line, ".\r\n") == 0) + break; + + /* grow */ + if (count >= cap) { + size_t ncap = cap * 2; + char** tmp = (char**)realloc(ov->lines, sizeof(char*) * ncap); + if (!tmp) + goto error; + + ov->lines = tmp; + cap = ncap; + } + + /* handle dot-stuffing */ + char* out = line; + if (out[0] == '.' && out[1] == '.') + out++; + + /* strip trailing newline */ + size_t len = strlen(out); + while (len && (out[len-1] == '\n' || out[len-1] == '\r')) + out[--len] = '\0'; + + ov->lines[count] = ANNTP_STRDUP(out); + if (!ov->lines[count]) + goto error; + + count++; + } + + ov->count = count; + return (ssize_t)count; + +error: + if (ov->lines) { + for (size_t i = 0; i < count; i++) + ANNTP_FREE(ov->lines[i]); + ANNTP_FREE(ov->lines); + } + + memset(ov, 0, sizeof(*ov)); + return ANNTPE(ANE_IO); +} + static char* anntp__trim_left(char* s) {