commit dd107d31c32bcc3fb7b4792060470e0cd4c40310
parent f656a66a6bf497e196458cd39dbccccba0935dbe
Author: Mario Rosell R. Martinez <mario@mariorosell.es>
Date: Fri, 20 Mar 2026 20:10:31 +0100
Import
Diffstat:
2 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
@@ -1,4 +1,3 @@
-*.c
*.swp
*.swo
a.out
diff --git a/examples/nntpsh.c b/examples/nntpsh.c
@@ -0,0 +1,158 @@
+/*
+ * anntp v0.1: nntpsh.c - example 1 - nntp shell
+ *
+ * This program basically connects to a host and allows you to run commands.
+ *
+ * Pretty basic, uses readdot_cb and writeline, as well as the basic lifecycle functions and standard C.
+ */
+
+#include <arpa/inet.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ANNTP_TLS
+#define ANNTP_IMPLEMENTATION
+#include "../anntp.h"
+
+static char host[0x100];
+static char port[0x10];
+static bool usetls;
+static AnntpConnection* c;
+
+/* anntp_readdot_cb callback */
+ static inline int
+puts_cb(const char* l, void* _)
+{
+ (void*)_;
+ printf("< %s", l);
+
+ return 0;
+}
+
+ static inline void
+cli(int argc, char** argv)
+{
+ if (argc < 3 || argc > 4) {
+ fprintf(stderr, "usage: %s <host> <port> [tls]\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (argc == 4) {
+ usetls = true;
+ } else {
+ usetls = false; /* initialize tls nevertheless */
+ }
+
+ /* copy host */
+ strncpy(host, argv[1], sizeof(host) - 1);
+ host[sizeof(host) - 1] = '\0';
+
+ /* copy port */
+ strncpy(port, argv[2], sizeof(port) - 1);
+ port[sizeof(port) - 1] = '\0';
+}
+
+void
+setup(void) {
+ c = anntp_mkconn(host, port, usetls);
+ if (!c) {
+ fprintf(stderr, "%s: can't create connection\n");
+ exit(EXIT_FAILURE);
+ }
+
+ char* ipstr = inet_ntoa(c->addr);
+ printf("Connected to host `%s' (%s)\n", host, ipstr);
+ puts("Use the `quit' command to exit.");
+}
+
+static void
+sendin(char line[512])
+{
+ if (line[0] == '\n' || line[0] == '\0')
+ return;
+
+ line[strcspn(line, "\n")] = 0; // remove newline
+
+ ssize_t n = anntp_writeline(c, line);
+
+ if (ANNTP_ISERR(n)) {
+ fprintf(stderr, "< error: %s\n", anntp_strerror(ANNTP_CODE(n)));
+ exit(EXIT_FAILURE);
+ }
+}
+
+void
+teardown(void) {
+ anntp_freeconn(c);
+}
+
+int
+main(int argc, char** argv)
+{
+ cli(argc, argv);
+ anntp_init();
+
+ setup();
+
+ /* read greeting */
+ char bbuf[4096];
+ ssize_t n = anntp_readline(c, bbuf, 4096);
+ if (ANNTP_ISERR(n)) {
+ fprintf(stderr, "< error: %s", anntp_strerror(ANNTP_CODE(n)));
+ return EXIT_FAILURE;
+ }
+
+ puts(bbuf);
+
+ for (;;) {
+ char line[512];
+
+ printf("nntp> ");
+ fflush(stdout);
+
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ fprintf(stderr, "%s: error reading input", argv[0]);
+ }
+
+ if (strncmp(line, "quit", 4) == 0) {
+ return EXIT_SUCCESS;
+ }
+
+ sendin(line);
+ char resp[4096];
+ n = anntp_readline(c, resp, sizeof(resp));
+
+ if (ANNTP_ISERR(n)) {
+ fprintf(stderr, "< error: %s", anntp_strerror(ANNTP_CODE(n)));
+ continue;
+ }
+
+ puts(resp);
+
+ int code = atoi(resp);
+
+ /* multiline responses */
+ switch (code) {
+ case 100: /* fallthrough */
+ case 101:
+ case 215:
+ case 220:
+ case 222:
+ case 224:
+ case 230:
+ case 231:
+ anntp_readdot_cb(c, puts_cb, NULL);
+ break;
+
+ default:
+ /* single line responses have nothing else to read */
+ break;
+ }
+ }
+
+ teardown();
+ return EXIT_SUCCESS;
+}
+