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:
| M | anntp.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)
{